digitalmars.D.bugs - [Issue 1491] New: if working with timed-out socket, SIGPIPE will kill program
- d-bugmail puremagic.com (51/51) Sep 10 2007 http://d.puremagic.com/issues/show_bug.cgi?id=1491
- Ingo Oeser (14/21) Sep 11 2007 No! NACK!
- Downs (23/54) Sep 11 2007 -----BEGIN PGP SIGNED MESSAGE-----
- Downs (36/36) Sep 11 2007 -----BEGIN PGP SIGNED MESSAGE-----
- Ingo Oeser (6/10) Sep 12 2007 That one was much better. Could you please fix the sendTo()
- Downs (66/82) Sep 12 2007 -----BEGIN PGP SIGNED MESSAGE-----
- Ingo Oeser (29/47) Sep 12 2007 Then simply don't touch them in a manner visible to the user.
- d-bugmail puremagic.com (9/9) Nov 03 2007 http://d.puremagic.com/issues/show_bug.cgi?id=1491
http://d.puremagic.com/issues/show_bug.cgi?id=1491 Summary: if working with timed-out socket, SIGPIPE will kill program Product: D Version: unspecified Platform: PC OS/Version: Linux Status: NEW Keywords: patch Severity: normal Priority: P2 Component: Phobos AssignedTo: bugzilla digitalmars.com ReportedBy: default_357-line yahoo.de On linux, when trying to work with a socket that has already expired, the signal SIGPIPE is raised. If unchecked, it will terminate the program. Since there is a defined behavior for trying to work with timed-out sockets (send/receive return -1), we can safely ignore this signal. The following patch for gdc's std/thread.d (should be equally applicable to dmd) implements this: diff socket.d.old socket.d -u --- socket.d.old 2007-09-11 03:05:54.000000000 +0200 +++ socket.d 2007-09-11 03:10:30.000000000 +0200 -126,6 +126,17 } } +version (Win32) { } +else +{ + extern(C) + { + typedef void function(int) sighandler_t; + sighandler_t signal(int signum, sighandler_t handler); + const int SIGPIPE=13; + const sighandler_t SIG_IGN=cast(sighandler_t)cast(void*)1; + } +} static this() { -140,6 +151,10 if(val) // Request Winsock 2.2 for IPv6. throw new SocketException("Unable to initialize socket library", val); } + else + { + signal(SIGPIPE, SIG_IGN); + } } --
Sep 10 2007
d-bugmail puremagic.com wrote:On linux, when trying to work with a socket that has already expired, the signal SIGPIPE is raised. If unchecked, it will terminate the program. Since there is a defined behavior for trying to work with timed-out sockets (send/receive return -1), we can safely ignore this signal. The following patch for gdc's std/thread.d (should be equally applicable to dmd) implements this:No! NACK! Signals are a global state. Libraries should never modify them in that manner, since the defaults are well documented in signal(7) and programs might expect this behaviour. The default setting for SIGPIPE is to terminate the program, which is correct for simple programs not handling signals at all. The preferred solution in Linux is to provide the flag MSG_NOSIGNAL in the flags parameter of send(2), sendto(2) and sendmsg(2). But this symbol must be generated by gen_unix.c first, if defined. (in function c_socket()) Best Regards Ingo Oeser
Sep 11 2007
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Ingo Oeser wrote:d-bugmail puremagic.com wrote:I disagree on this. The only behavior std/socket.d should exhibit is the behavior documented in http://digitalmars.com/d/phobos/std_socket.html. Unix signals are a platform specific feature that somebody writing a platform independent program should _not_ have to mess with.On linux, when trying to work with a socket that has already expired, the signal SIGPIPE is raised. If unchecked, it will terminate the program. Since there is a defined behavior for trying to work with timed-out sockets (send/receive return -1), we can safely ignore this signal. The following patch for gdc's std/thread.d (should be equally applicable to dmd) implements this:No! NACK! Signals are a global state. Libraries should never modify them in that manner, since the defaults are well documented in signal(7) and programs might expect this behaviour.The default setting for SIGPIPE is to terminate the program, which is correct for simple programs not handling signals at all.But this behavior is neither documented in std_socket.html, nor is it platform independent, nor is there a platform independent way to _prevent it_.The preferred solution in Linux is to provide the flag MSG_NOSIGNAL in the flags parameter of send(2), sendto(2) and sendmsg(2).Okay, well great! If there's a proper way to suppress this behavior, by all means, let's do that instead! But please, don't force the user to write platform dependent code. That's what standard libraries are for.But this symbol must be generated by gen_unix.c first, if defined. (in function c_socket())Right, my patch isn't very clean. It was mainly along the lines of "hey, this worked for me" :)Best Regards Ingo Oeser--downs -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.7 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iD8DBQFG52pepEPJRr05fBERAkhJAJ9Bv4DsPUvQQwKJQ1yC8lbKSP4hrgCgg0AT yPxQCb9/hgAt0vng8rKJ/zE= =jS6v -----END PGP SIGNATURE-----
Sep 11 2007
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Alright, here's a revised version of the patch. diff config/gen_unix.c.old config/gen_unix.c -u; diff -u std/socket.d.old std/socket.d - --- config/gen_unix.c.old 2007-09-12 06:33:55.000000000 +0200 +++ config/gen_unix.c 2007-09-12 06:29:01.000000000 +0200 -667,6 +667,7 CES( MSG_OOB ); CES( MSG_PEEK ); CES( MSG_DONTROUTE ); + CES( MSG_NOSIGNAL ); printf("}\n"); printf("\n"); } - --- std/socket.d.old 2007-09-11 03:05:54.000000000 +0200 +++ std/socket.d 2007-09-12 06:37:08.000000000 +0200 -1335,6 +1335,11 //returns number of bytes actually sent, or -1 on error int send(void[] buf, SocketFlags flags) { + version(Windows) { } + else + { + flags |= MSG_NOSIGNAL; + } int sent = .send(sock, buf.ptr, buf.length, cast(int)flags); return sent; } -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.7 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iD8DBQFG528HpEPJRr05fBERAmUiAJ9ZeCIXYZ9i1nrAzxsu2VaamtoEEQCggw/r C7/6C3M8RK0c/PTZzH7/dFM= =ZjqC -----END PGP SIGNATURE-----
Sep 11 2007
Downs wrote:-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Alright, here's a revised version of the patch.That one was much better. Could you please fix the sendTo() method calling .sendto(), too? Many thanks! Best Regards Ingo Oeser
Sep 12 2007
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Ingo Oeser wrote:Downs wrote:Sorry, I forgot. Sec .. diff config/gen_unix.c.old config/gen_unix.c -u; diff -u std/socket.d.old std/socket.d - --- config/gen_unix.c.old 2007-09-12 06:33:55.000000000 +0200 +++ config/gen_unix.c 2007-09-12 06:29:01.000000000 +0200 -667,6 +667,7 CES( MSG_OOB ); CES( MSG_PEEK ); CES( MSG_DONTROUTE ); + CES( MSG_NOSIGNAL ); printf("}\n"); printf("\n"); } - --- std/socket.d.old 2007-09-11 03:05:54.000000000 +0200 +++ std/socket.d 2007-09-13 03:10:54.000000000 +0200 -1335,6 +1335,11 //returns number of bytes actually sent, or -1 on error int send(void[] buf, SocketFlags flags) { + version(Windows) { } + else + { + flags |= MSG_NOSIGNAL; + } int sent = .send(sock, buf.ptr, buf.length, cast(int)flags); return sent; } -1350,6 +1355,11 */ int sendTo(void[] buf, SocketFlags flags, Address to) { + version(Windows) { } + else + { + flags |= MSG_NOSIGNAL; + } int sent = .sendto(sock, buf.ptr, buf.length, cast(int)flags, to.name(), to.nameLen()); return sent; } -1365,6 +1375,11 /// ditto int sendTo(void[] buf, SocketFlags flags) { + version(Windows) { } + else + { + flags |= MSG_NOSIGNAL; + } int sent = .sendto(sock, buf.ptr, buf.length, cast(int)flags, null, 0); return sent; } Excuse the copypaste, but I wasn't sure whether it was worth it making a new private function for this. --downs -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.7 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iD8DBQFG6I6apEPJRr05fBERAkDXAKCaDYixAXUHIc31yvaPMAGNC46liACfZ1Za wx9sEDj0PtbwQHct6B6GxfQ= =rpSm -----END PGP SIGNATURE----------BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Alright, here's a revised version of the patch.That one was much better. Could you please fix the sendTo() method calling .sendto(), too? Many thanks! Best Regards Ingo Oeser
Sep 12 2007
Downs wrote:Ingo Oeser wrote:Then simply don't touch them in a manner visible to the user. Doing that is as useful as keeping locks open, which is also not documented. Principle of least surprise should be applied here. If you write a Unix daemon (sth. like a service in Windows), you need to handle signals in a defined way. There is no way around that, since your desired behaviour depends on your needs. Face it: Windows and Unix are so different, that anything more complex than "hello world" needs to handle the subtle differences anyway.Signals are a global state. Libraries should never modify them in that manner, since the defaults are well documented in signal(7) and programs might expect this behaviour.Unix signals are a platform specific feature that somebody writing a platform independent program should _not_ have to mess with.Interaction of between phobos and Unix systems is not documented in any *.html at all. This leads to hard to find bugs, since many API details are only documented in the man pages on Unix systems and the API is implemented in the matching C libraries (e.g. the glibc on Linux). I'm happy, that I have the sources of the standard library to be able to find such side effects :-)The default setting for SIGPIPE is to terminate the program, which is correct for simple programs not handling signals at all.But this behavior is neither documented in std_socket.html, nor is it platform independent,nor is there a platform independent way to _prevent it_.Correct! By googling around a bit I found another way to do this, if MSG_NOSIGNAL is not available: setsockopt() with SO_NOSIGPIPE. This might prevent the same problem on MacOS X. But I don't have the docs for that one. If everything else fails, one can ignore SIGPIPE before send() and sendTo() and restore the old signal behaviour after the call. That is inefficient, but at least correct and as transparent as possible.Okay, well great! If there's a proper way to suppress this behavior, by all means, let's do that instead! But please, don't force the user to write platform dependent code. That's what standard libraries are for.Of course not! Yes, but the standard library is also the one, which has to be compatible in program behaviour with any other library. How useful is a standard library, which doesn't work with millions of lines of code written already? I like revolutionary ideas, but the should integrate in practise. Best Regards Ingo Oeser
Sep 12 2007
http://d.puremagic.com/issues/show_bug.cgi?id=1491 bugzilla digitalmars.com changed: What |Removed |Added ---------------------------------------------------------------------------- Status|NEW |RESOLVED Resolution| |FIXED ------- Comment #4 from bugzilla digitalmars.com 2007-11-03 21:48 ------- Fixed dmd 1.023 --
Nov 03 2007