is socket thread safe?

Bryan Olson fakeaddress at nowhere.org
Wed Feb 15 21:04:59 EST 2006


Carl J. Van Arsdall wrote:
> Steve Horsley wrote:
> 
>> e2wugui at gmail.com wrote:
>>  
>>
>>> thread1:
>>>     while 1:
>>>         buf = s.read()
>>>         process(buf)
>>>
>>> thread2:
>>>     while 1:
>>>         buf = getdata()
>>>         s.write(buf)    
>>
>>
>> It is safe, but watch out for this gotcha: If thread B calls s.close() 
>> while thread A is blocked in s.read(), thread A will never return from 
>> the read. My preferred solution is to set socket timeout to a few 
>> seconds, and loop checking a status flag so I know when to quit.

Certainly one needs timeouts to avoid hanging should the remote
side stop. Sockets don't have a read() method, and hanging on
recv() doesn't seem to have anything to do with close().

I didn't find any definitive doc, so I tested using Python
sockets on Linux (Debian/Ubuntu current) and WinXP. A recv()
started before the close() will block/return just as if
close() were never called. The close() neither triggers recv()
to abort, nor prevents it from receiving data and detecting
shutdown.


> I think a better thing would be to use something like a condition object 
> to tie the two threads together and not use any polling loops.
> 
> i.e.  consumer goes to sleep while data buffer is empty, producer 
> produces and signals condition object, consumer wakes up and consumes.

I can infer two producer-consumer relationships from the example,
but they don't allow a condition object; the writer's consumer and
the reader's producer are on the remote end of the socket. The
socket will already handle the blocking and wake-up.

> To take this a step further, you have a status flag that is set to 
> something like QUIT or CONSUME and when the condition is triggered wake 
> up, then examine the status flag to determine if the consumer should 
> then quit, consume, or whatever else you'd want your consumer thread to do.

What problem are you trying to solve? Normal socket sending, receiving,
and shutdown discipline work fine. When the writer is done writing, it
should call sock.shutdown(socket.SHUT_WR). When the reader gets zero
bytes from recv(nonzero), that means the remote end has finished
writing, so the reader may call sock.shutdown(socket.SHUT_RD).


-- 
--Bryan



More information about the Python-list mailing list