Reputation: 11
I am developing a program that uses Twisted and wxReactor. Everytime I try to exit the application, it hangs, and I have to force quit it. My wxPython OnClose() event does call reactor.stop(), which to my knowledge should fix this issue. In my quest for an answer, I've come across this ticket: www.twistedmatrix.com/trac/ticket/3948.
I've tried a patch listed on the page, with no luck. I've been at this problem for 2 weeks now, and am pretty desperate :).
To give you all some background on this project: It is a freeware client that uses sockets to connect to a multiplayer game server (currently plays Monopoly and Uno). If you run it, you will immediately notice there are no graphics. That is because this client only provides audio feedback through speech synthesis and sound effects. The target audience of this project is visually impaired gamers.
To test the issue, run python rsg.py (which can be found in the src folder. In case you need to know, I use Python 2.6.5). In a terminal, you will see the output the program produces (which is mostly what the server sends to our client). Once you see the line "Connection Made" (which should print very shortly after running), try closing the program (by clicking the X). The client will hang for a few seconds, and then you will need to force quit the application (on Ubuntu, it comes up asking if I want to force quit the application).
I do have an idea of why it doesn't exit properly. When I ran it through gdb, two threads weren't exiting. Strange enough, if the server closed the connection, then I exited the program, it would work fine.
I really appreciate all help. Thank you in advance.
Edit Since I was asked to provide a basic demo of my problem, here it is:
import wx
import sys
from twisted.internet import wxreactor
wxreactor.install()
# import t.i.reactor only after installing wxreactor:
from twisted.internet import reactor
from twisted.protocols.basic import LineReceiver
from twisted.internet.protocol import ClientFactory
class ZGPClient(LineReceiver):
"""Our client object."""
def lineReceived(self, datavar):
"As soon as any data is received"
print datavar
class EchoFactory(ClientFactory):
protocol = ZGPClient
def startedConnecting(self, connector):
global conn
conn = connector
print 'Started to connect.'
def sendData(self, data=""):
conn.transport.write(data.encode("ascii", "ignore") + "\n")
class main_window(wx.Frame):
def __init__(self, parent, id, title):
super(main_window, self).__init__(parent, id, title, style=wx.DEFAULT_FRAME_STYLE)
self.Bind(wx.EVT_CLOSE, self.OnClose)
self.Show(True)
def OnClose(self, event):
reactor.stop()
sys.exit()
if __name__ == "__main__":
app = wx.App()
frame = main_window(None, wx.ID_ANY, "RS Games Client - No Game")
reactor.registerWxApp(app)
sockObj = EchoFactory()
reactor.connectTCP("rsgamesmonserver.webhop.org", 3555, sockObj)
reactor.run()
app.MainLoop()
Upvotes: 1
Views: 571
Reputation: 39
This will work for you:
def OnClose(self, evt):
# ugly hack until wxreactor is patched:
reactor._stopping = True
reactor.callFromThread(_threadedselect.ThreadedSelectReactor.stop, reactor)
Upvotes: 2
Reputation: 405
I had the same problem in one of my projects. I just need to remove following code:
When you're using twisted, the reactor is driving your application. By stopping the reactor, you're also stopping the whole application. The problem might be caused by exception raised from sys.exit() (if it does, I'm not sure), since reactor is catching all the exceptions and reporting to console.
Just remember, when you're using twisted, or other similar framework, you must think in a little bit different way (Inversion of control). Also, I recommend reading this great tutorial series on Asynchronous Programming and Twisted.
The reactor must be calling MainLoop() inside it's run method. In your code, you're launching two main loops, and you'll need to close your main window twice to exit.
Upvotes: 0