Bug 1491 – if working with timed-out socket, SIGPIPE will kill program
Status
RESOLVED
Resolution
FIXED
Severity
normal
Priority
P2
Component
phobos
Product
D
Version
D2
Platform
x86
OS
Linux
Creation time
2007-09-10T20:16:00Z
Last change time
2015-06-09T05:14:57Z
Keywords
patch
Assigned to
bugzilla
Creator
default_357-line
Comments
Comment #0 by default_357-line — 2007-09-10T20:16:57Z
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);
+ }
}
Comment #1 by default_357-line — 2007-09-11T23:30:27Z
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Ingo Oeser wrote:
> [email protected] 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.
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.
>
> 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-----
Comment #2 by default_357-line — 2007-09-11T23:50:39Z
-----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-----
Comment #3 by default_357-line — 2007-09-12T20:15:19Z
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Ingo Oeser wrote:
> 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
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-----