safely closing a socket?

Donn Cave donn at u.washington.edu
Fri Sep 26 19:13:49 EDT 2003


In article <rowen-BB1C2E.13503026092003 at nntp2.u.washington.edu>,
 "Russell E. Owen" <rowen at cesmail.net> wrote:

> I've been doing some socket programming with threads and am confused how 
> to safely shut down a connection.
> 
> First of all, using the file-like object returned by urllib to do ftp 
> file download (Python 2.3, MacOS X), I can hang the process by:
> - using one thread to read the file-like object
> - trying to close the connection in the main thread (while still 
> downloading)
> it's not clear to me what's hung, but it just sits there. No major CPU 
> cycles being eaten. Some kind of deadlock, perhaps???
> 
> I've worked around the problem by setting a flag and having the read 
> thread quit. But this can take quite awhile. Is there some fast safe way 
> to terminate such a download?
> 
> Also, is this more generally an issue with sockets? Is it dangerous to 
> close a socket while another thread may be reading or writing it?

Greetings, Russell!  It depends on the platform.

Casual experiment with two variations -

  1.  child thread in socketobject.recv(), parent
      calls socketobject.close()

    MacOS X:          recv returns ''
    FreeBSD 5.1:      recv raises exception (errno EBADF)
    Redhat Linux 7.2: recv continues

  2.  child thread in socketobject.makefile('r').read(),
      parent calls socketobject.close()

    MacOS X:          read continues
    FreeBSD 5.1:      read continues
    Redhat Linux 7.2: read continues, program doesn't exit

So there seems to be an incentive to avoid the file object
thing, but you couldn't depend on that working on every
possible platform (e.g., Linux.) 

One sort of deluxe option would be an inter-thread communications
channel, probably a pipe, that the child thread reads along
with its socket, via select().  It won't interrupt a recv
actually in progress, transferring data, but ordinarily the
intent is to abort it when it would be waiting for more data.
This doesn't work well with fileobject I/O, has to be system
level posix.read or socketobject.recv.

   Donn Cave, donn at u.washington.edu




More information about the Python-list mailing list