http://d.puremagic.com/issues/show_bug.cgi?id=4457

           Summary: Sockets on OSX terminate apps with SIGPIPE and there's
                    no (official) way to turn it off
           Product: D
           Version: D2
          Platform: Other
        OS/Version: Mac OS X
            Status: NEW
          Severity: normal
          Priority: P2
         Component: Phobos
        AssignedTo: nob...@puremagic.com
        ReportedBy: soul...@gmail.com


--- Comment #0 from Heywood Floyd <soul...@gmail.com> 2010-07-13 22:18:44 PDT 
---
Short: std.sockets makes it so that sockets do not throw SIGPIPE with the
NOSIGNAL flag in each call to 'send' and 'receive'. OSX does not support this,
but requires that one turn off SIGPIPE with 'setsockopt' once for each socket
with the flag SO_NOSIGPIPE, which is not present in socket.d.

// - - - - - - 
//sigpipe.d
import     std.socket;
void main(){
    auto socket = new TcpSocket();
    auto address = new InternetAddress("127.0.0.1", 8000);

        //Uncommenting these lines fixes the problem.
    //immutable int SO_NOSIGPIPE =    0x1022; // From socket.h (Apple)
    //socket.setOption(SocketOptionLevel.SOCKET,
cast(SocketOption)SO_NOSIGPIPE, cast(void[])[1]);

    socket.bind(address);
    socket.blocking(true);
    socket.listen(10);
    auto newSocket = socket.accept();

    foreach(i;0..50000)
        newSocket.send("HTTP/1.0 200 OK\r\nContent-Length: 5\r\n\r\nHello");    
}
// - - - - - - 

$ dmd -debug sigpipe
$ gdb sigpipe
...
(gdb) run
...
* Open up a web-browser and open the URL "http://127.0.0.1:8000";. The web
browser needs to understand that the data stream is baloney and shut the
connection down. Chrome, Firefox and Safari "works" for me.
...
Program received signal SIGPIPE, Broken pipe.
0x987ebdc2 in sendto$NOCANCEL$UNIX2003 ()
(gdb) _

// - - - - - - 

(Note: Gdb is needed because the SIGPIPE is not visible from the command line.
(Because it's really a "feature" for doing unix piping stunts. But I'm
preaching to the choir...))

A look in socket.d shows:

// - - - - - - 
    int send(const(void)[] buf, SocketFlags flags)
    {
                flags |= SocketFlags.NOSIGNAL;
        int sent = .send(sock, buf.ptr, buf.length, cast(int)flags);
        return sent;
    }
// - - - - - - 

The above is supposed to suppress SIGPIPEs. Only as far as I can tell, from the
header files on OSX, the equivalent of the NOSIGNAL-flag does simply not exist.

Further down we find the SocketOptions enums:

// - - - - - - 
enum SocketOption: int
{
    DEBUG =                SO_DEBUG,    /// record debugging information
    BROADCAST =            SO_BROADCAST,    /// allow transmission of broadcast
messages
    REUSEADDR =            SO_REUSEADDR,    /// allow local reuse of address
    LINGER =               SO_LINGER,    /// linger on close if unsent data is
present
    OOBINLINE =            SO_OOBINLINE,    /// receive out-of-band data in
band
    SNDBUF =               SO_SNDBUF,    /// send buffer size
    RCVBUF =               SO_RCVBUF,    /// receive buffer size
    DONTROUTE =            SO_DONTROUTE,    /// do not route
        //...
// - - - - - - 

Here, SO_NOSIGPIPE is missing for OSX.

I understand that this may have implications on the whole design of sockets, as
they have obviously been designed to suppress SIGPIPE by default. (Which makes
sense to me.) Because OSX has a different way of suppressing that, there arises
some difficulty for a developer who wishes to control this behaviour, without
knowing all platforms by heart. I'm just saying, seems to me it's not just as
easy as throwing in this constant and having SIGPIPE turned off by default. How
will you turn it on again? And that's why I stop here before I come up with any
silly ideas : )

BR
/HF

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------

Reply via email to