WebSocket-for-Python icon indicating copy to clipboard operation
WebSocket-for-Python copied to clipboard

RuntimeError('threads can only be started once',)

Open nicklasb opened this issue 10 years ago • 4 comments

Hi, I am having this strange problem, I am writing tests on restarting a websocket enabled CherryPy server, and for some reason, when I by using runpy.run_module starts a new process instance, I get the "threads can only be started once"-error. But strangely, not in the first instance, which I am careful to properly clean up. Not sure how anything could be carried over to the new process, but I started barking up every tree in the end.

So this is the initialization:

  1. I have these in the config for the relevant path:

        "tools.websocket.on": True,
        "tools.websocket.handler_cls": MessageWebSocket 
    
  2. I start the engine like this, fairly conventional, I'd think:

    cherrypy._global_conf_alias.update(_web_config)
    WebSocketPlugin(cherrypy.engine).subscribe() # If I remove this row, CherryPy restart nominally
    cherrypy.tools.websocket = WebSocketTool()
    
    cherrypy.quickstart(_root, "/", _web_config)
    
  3. And then I get this 'threads can only be started once', error in WebSocketPlugin, when it called start, I have added a condition there to just make it work for now, obviously that is not a long-term solution:

    def start(self):
        self.bus.log("Starting WebSocket processing")
        self.bus.subscribe('stop', self.cleanup)
        self.bus.subscribe('handle-websocket', self.handle)
        self.bus.subscribe('websocket-broadcast', self.broadcast)
        if not self.manager._started.is_set(): # this row added by me
            self.manager.start()
    

Any ideas? It seems very strange that only web socket would fail, could it be that it doesn't release something properly in the first process instance? Which has already called os._exit() by this time, and I get no issues with sockets kept open either.

nicklasb avatar Jun 05 '15 01:06 nicklasb

Ok. I have now verified that it calls it twice in the second process instance, and not in the first. AFAIK they are identical, the application is calling itself. Weird.

nicklasb avatar Jun 05 '15 01:06 nicklasb

Ok # 2: Now, I have no idea why this works: But manually calling the web socket plugin instance's unsubscribe method in the first process instance, causes WebSocketPlugin.start() to only be called once in the second instance. Now I don't need to change any ws4py-code.

But shouldn't the WebSocketPlugin be automatically unsubscribed? The old process is dead, is there some handler somewhere I don't know of that is locking something? Many questions.

nicklasb avatar Jun 05 '15 01:06 nicklasb

Heya,

i'm trying to make my head around your issue here. Would you have a simple example demonstrating the behavior I could run on my side? Also, which versions of Python/CP/ws4py are you running?

Lawouach avatar Jun 05 '15 07:06 Lawouach

It is a really complicated setup with multiple processes, so I am having problems making a reproducible example, it seems to have something to do with orphaned sockets, but I am not sure. I'll be back.

nicklasb avatar Jun 09 '15 10:06 nicklasb