New submission from Justin Cappos <justincap...@gmail.com>: Suppose there is a program that has a listening socket that calls accept to obtain new sockets for client connections. socketmodule.c assumes that these client sockets have timeouts / blocking in the default state for new sockets (which on most systems means the sockets will block). However, socketmodule.c does not verify the state of the socket object that is returned by the system call accept.
>From http://linux.die.net/man/2/accept : On Linux, the new socket returned by accept() does not inherit file status flags such as O_NONBLOCK and O_ASYNC from the listening socket. This behaviour differs from the canonical BSD sockets implementation. Portable programs should not rely on inheritance or non-inheritance of file status flags and always explicitly set all required flags on the socket returned from accept(). socketmodule.c does not explicitly set or check these flags for sockets returned by accept. The attached program will print the following on Linux regardless of whether the settimeout line for s exists or not: a has timeout: None O_NONBLOCK is set: False received: hi On Mac / BSD, the program will produce the following output when the timeout is set on the listening socket: a has timeout: None O_NONBLOCK is set: True Traceback (most recent call last): File "python-nonportable.py", line 39, in <module> message = a.recv(1024) socket.error: (35, 'Resource temporarily unavailable') When the timeout is removed, the behavior is the same as linux: a has timeout: None O_NONBLOCK is set: False received: hi Note that the file descriptor problem crops up in odd ways on Mac systems. It's possible that issue 5154 may be due to this bug. I am aware of other problems with the socketmodule on Mac and will report them in other tickets. I believe that this problem can be easily mitigated by always calling fcntl to unset the O_NONBLOCK flag after accept (O_ASYNC should be unset too, for correctness). I would recommend adding the below code snippet at line 1653 in socketmodule.c (r78335). The resulting code would look something like this (with '+' in front of the added lines): ''' #ifdef MS_WINDOWS if (newfd == INVALID_SOCKET) #else if (newfd < 0) #endif return s->errorhandler(); +#if defined(__APPLE__) || defined(__OpenBSD__) || defined(__FreeBSD__) + int starting_flag; + // Unset O_NONBLOCK an O_ASYNC if they are inherited. + starting_flag = fcntl(newfd, F_GETFL, 0); + starting_flag &= ~(O_NONBLOCK | O_ASYNC); + fcntl(newfd, F_SETFL, starting_flag); +#endif /* Create the new object with unspecified family, to avoid calls to bind() etc. on it. */ sock = (PyObject *) new_sockobject(newfd, s->sock_family, s->sock_type, s->sock_proto); ''' I've tested this patch on my Mac and Linux systems and it seems to work fine. I haven't had a chance to test on BSD. Also, I did not test for this problem in Python 3, but I assume it exists there as well and the same fix should be applied. ---------- assignee: ronaldoussoren components: Library (Lib), Macintosh files: python-nonportable.py messages: 99852 nosy: Justin.Cappos, bbangert, giampaolo.rodola, loewis, nicdumz, ronaldoussoren severity: normal status: open title: On Mac / BSD sockets returned by accept inherit the parent's FD flags type: behavior versions: Python 2.5, Python 2.6, Python 2.7 Added file: http://bugs.python.org/file16325/python-nonportable.py _______________________________________ Python tracker <rep...@bugs.python.org> <http://bugs.python.org/issue7995> _______________________________________ _______________________________________________ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com