python errors with popen/threads/select
Satish Balay
balay@fastmail.fm
Sat Mar 24 19:16:00 GMT 2007
We are encountering errors in our python code when invoking system
commands using popen2.Popen3() in a separate thread. This code works
fine on linux [and many other OSes ] - but not on cygwin/python/WinXP.
I'm attaching a minimal example code that demonstrates this problem.
This test code runs the command '/bin/true' in 2 modes. [multiple
times in a loop]
- run the command in a separate thread [using popen]
- run the command directly [using popen]
The thread version fails numerous times [with wait() on pipe returning
error codes] - whereas the one run directly does not.
Hoping the bug can be identified.
thanks,
Satish
----------------------------
$ /usr/bin/cygcheck.exe -c cygwin python
Cygwin Package Information
Package Version Status
cygwin 1.5.24-2 OK
python 2.5-1 OK
$ python th-bug.py
pipe.wait() returns error code: 1280
pipe.wait() returns error code: 1280
pipe.wait() returns error code: 1280
pipe.wait() returns error code: 1280
pipe.wait() returns error code: 1280
pipe.wait() returns error code: 1280
pipe.wait() returns error code: 1280
pipe.wait() returns error code: 1280
pipe.wait() returns error code: 1280
pipe.wait() returns error code: 1280
thread+pipe overhead 2.47299981117
pipe overhead 2.26300001144
-------------- next part --------------
import popen2
import threading
import time
import os
timeout = 10
def openPipe(command):
'''We need to use the asynchronous version here since we want to avoid blocking reads'''
pipe = popen2.Popen3(command, 1)
input = pipe.tochild
output = pipe.fromchild
err = pipe.childerr
return (input, output, err, pipe)
def runShellCommand(command):
import select
ret = None
out = ''
err = ''
count = 0
(input, output, error, pipe) = openPipe(command)
input.close()
lst = [output, error]
while lst:
ready = select.select(lst, [], [])
count = count + 1 # somehow this line triggers the bug more frequently
if len(ready[0]):
if error in ready[0]:
msg = error.readline()
if msg:
err += msg
else:
lst.remove(error)
if output in ready[0]:
msg = output.readline()
if msg:
out += msg
else:
lst.remove(output)
output.close()
error.close()
if pipe:
ret = pipe.wait()
if ret: print 'pipe.wait() returns error code:', ret
return (out, err, ret)
#####################################################
def runThreadShellCommand(command):
thread = threading.Thread(target = runShellCommand, name = 'Shell Command', args = (command,))
thread.setDaemon(1)
thread.start()
thread.join(timeout)
return 0
time1 = time.time()
for count in range(0,30):
runThreadShellCommand('/bin/true')
time2 = time.time()
print 'thread+pipe overhead',time2-time1
time1 = time.time()
for count in range(0,30):
runShellCommand('/bin/true')
time2 = time.time()
print 'pipe overhead', time2-time1
-------------- next part --------------
--
Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple
Problem reports: http://cygwin.com/problems.html
Documentation: http://cygwin.com/docs.html
FAQ: http://cygwin.com/faq/
More information about the Cygwin
mailing list