Reputation: 1629
I was trying to run a program in python that opens a program and read from its stdout. When i run the program code i got a segmentation Fault error, but when i put the code inside the function Myfunc out of the thread it work perfectly! I dont understand what is happening: Here is my code:
class Workspace(QMainWindow, Ui_MainWindow):
""" This class is for managing the whole GUI `Workspace'.
Currently a Workspace is similar to a MainWindow
"""
def __init__(self):
#p= subprocess.Popen(["java -Xmx256m -jar bin/HelloWorld.jar"],cwd=r'/home/karen/sphinx4-1.0beta5-src/sphinx4-1.0beta5/', shell=True, stdout=subprocess.PIPE, bufsize= 4024)
try:
from Queue import Queue, Empty
except ImportError:
while True:
#from queue import Queue, Empty # python 3.x
print "error"
ON_POSIX = 'posix' in sys.builtin_module_names
def enqueue_output(out, queue):
for line in iter(out.readline, b''):
queue.put(line)
out.close()
p= Popen(["java -Xmx256m -jar bin/HelloWorld.jar"],cwd=r'/home/karen/sphinx4-1.0beta5-src/sphinx4-1.0beta5/',stdout=PIPE, shell=True, bufsize= 4024)
q = Queue()
t = threading.Thread(target=enqueue_output, args=(p.stdout, q))
#t = Thread(target=enqueue_output, args=(p.stdout, q))
t.daemon = True # thread dies with the program
t.start()
# ... do other things here
def myfunc(q):
while True:
try: line = q.get_nowait()
# or q.get(timeout=.1)
except Empty:
print('Vacio')
else: # got line
# ... do something with line
print line
thread = threading.Thread(target=myfunc, args=(q,))
thread.start()
The error:
Segmentation fault (core dumped)
Upvotes: 4
Views: 4849
Reputation: 8200
I have experienced the same problem recently. I have quite a few calls of shell command via subprocess from dependent GUI threads that are working just fine, but one just refuses to work correctly and segfaults. The difference I have came to is exactly in the fact that I'm trying to run it from the main GUI thread and it was segfaulting when i was trying to emit a signal that was usually emitted from subthread!
My solution to avoid segfaulting was to move the part of dialog that required some shell involvement to a separate QThread, effectively inheriting the same common class that other threads in my app are using. The problem is gone! QThread is the key!
Code schema:
class Dialog(QtGui.QDialog):
def __init__(self):
...
QtCore.QObject.connect(self.ui.listwidget_a, QtCore.SIGNAL("itemClicked(QListWidgetItem)", self.do_work)
...
def do_work(self, qlistwidgetitem):
...
wc = WorkerClass(str(qlistwidgetitem.text()))
wc.start()
wc.wait()
my_result = wc.getResult()
class WorkerClass(CommonClass):
string = ""
result = ""
def __init__(string)
super(WorkerClass, self).__init__()
self.string = string
def run():
self.execute_shell(self.string)
self.result = self.shell_output
def get_result(self):
return self.result
class CommonClass(QtCore.QThread):
self.shell_output = ""
def execute_shell(string):
...
p = Popen(...)
self.shell_output, self.shell_error = p.communicate()
self.output_ready.emit(self.shell_output)
# that last line is where i was segfaulting
# before I made WorkerClass (my dialog class was
# inherinting CommonClass directly but it wasn't
# working in separate thread)
I hope that will help!
Upvotes: 5