how do i keep closing a subthread from closing the stdin file descriptor?
Clash Royale CLAN TAG#URR8PPP
how do i keep closing a subthread from closing the stdin file descriptor?
I wrote this bit of code to clarify my issue... I keep getting ValueError: I/O operation on closed file.
None of the child threads read from stdin. The loop works great until I start a child thread... can someone tell me how to keep the file descriptor from closing?
import threading
from threadtest2 import Threadtest
import termios, sys, tty
import time
def getchar():
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
try:
tty.setraw(sys.stdin.fileno())
ch = sys.stdin.read(1)
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
return ch
tt2 = Threadtest()
stop = threading.Event()
t1 = threading.Thread(target=tt2.thread1, args=[stop, ])
t2 = threading.Thread(target=tt2.thread2, args=[stop, ])
try:
while 1:
while not stop.isSet():
try:
c = getchar()
except IOError: pass
if c == "q":
stop.set()
if c == "x":
stop.set()
exit()
if c == "1":
print "starting t1"
t1.start()
if c == "2":
print "starting t2"
t2.start()
while len(threading.enumerate()) > 1:
print 'waiting for ' + str(len(threading.enumerate()) - 1) + ' threads to closer'
time.sleep(1)
stop.clear()
print "stop has been triggered and reset... restart"
finally:
print "done!"
there have been a few other threads (pardon the pun) that touched on this, but I haven't found one that directly addresses it and have been flailing for a while.
FYI, the child threads just wait for stop to be set and sleep...
1 Answer
1
I made small changes to your code to run it standalone. The following does not generate the error for me on a Linux machine. Do you still see the error with it? If so, I'd be glad to improve the answer - please give a few more details about how you are running the code such the operating system in use.
import threading
import termios, sys, tty
import time
def getchar():
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
try:
tty.setraw(sys.stdin.fileno())
ch = sys.stdin.read(1)
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
return ch
class Threadtest:
def thread1(self, stop):
stop.wait()
print "returning from thread1"
def thread2(self, stop):
stop.wait()
print "returning from thread2"
tt2 = Threadtest()
stop = threading.Event()
try:
while 1:
t1 = threading.Thread(target=tt2.thread1, args=[stop, ])
t2 = threading.Thread(target=tt2.thread2, args=[stop, ])
while not stop.isSet():
try:
c = getchar()
except IOError: pass
if c == "q":
stop.set()
if c == "x":
stop.set()
sys.exit()
if c == "1":
print "starting t1"
t1.start()
if c == "2":
print "starting t2"
t2.start()
print "waiting for threads to close".format(threading.active_count() - 1)
for t in [t1, t2]:
t.join()
stop.clear()
print "stop has been triggered and reset... restart"
finally:
print "done!"
The joins may not be necessary in Python. I added them just in case. It's just habit from cleaning up thread and forked processes in C. I was never able to reproduce exact error you saw. I also moved where the threads are created so new ones are made can be started after pressing Q.
– kentavv
Aug 13 at 14:16
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
this does in fact work! but I can't figure out how this doesn't produce the error while my code does. is it the join statements that allow it to work properly?
– th0th
Aug 13 at 13:53