@@ -34,18 +34,28 @@ def setup(self):
3434
3535 def handle (self ):
3636 self .delegate .start ()
37+ # pylint: disable=no-member
38+ self .SHUTDOWN_CALL ()
3739
3840
3941def start_tcp_lang_server (bind_addr , port , check_parent_process , handler_class ):
4042 if not issubclass (handler_class , PythonLanguageServer ):
4143 raise ValueError ('Handler class must be an instance of PythonLanguageServer' )
4244
45+ def shutdown_server (* args ):
46+ # pylint: disable=unused-argument
47+ log .debug ('Shutting down server' )
48+ # Shutdown call must be done on a thread, to prevent deadlocks
49+ stop_thread = threading .Thread (target = server .shutdown )
50+ stop_thread .start ()
51+
4352 # Construct a custom wrapper class around the user's handler_class
4453 wrapper_class = type (
4554 handler_class .__name__ + 'Handler' ,
4655 (_StreamHandlerWrapper ,),
4756 {'DELEGATE_CLASS' : partial (handler_class ,
48- check_parent_process = check_parent_process )}
57+ check_parent_process = check_parent_process ),
58+ 'SHUTDOWN_CALL' : shutdown_server }
4959 )
5060
5161 server = socketserver .TCPServer ((bind_addr , port ), wrapper_class )
@@ -78,6 +88,7 @@ def __init__(self, rx, tx, check_parent_process=False):
7888 self .workspace = None
7989 self .config = None
8090 self .root_uri = None
91+ self .watching_thread = None
8192 self .workspaces = {}
8293 self .uri_workspace_mapper = {}
8394
@@ -187,19 +198,18 @@ def m_initialize(self, processId=None, rootUri=None, rootPath=None, initializati
187198 self ._dispatchers = self ._hook ('pyls_dispatchers' )
188199 self ._hook ('pyls_initialize' )
189200
190- if self ._check_parent_process and processId is not None :
201+ if self ._check_parent_process and processId is not None and self . watching_thread is None :
191202 def watch_parent_process (pid ):
192203 # exit when the given pid is not alive
193204 if not _utils .is_process_alive (pid ):
194205 log .info ("parent process %s is not alive" , pid )
195206 self .m_exit ()
196- log .debug ("parent process %s is still alive" , pid )
197- threading .Timer (PARENT_PROCESS_WATCH_INTERVAL , watch_parent_process , args = [pid ]).start ()
198-
199- watching_thread = threading .Thread (target = watch_parent_process , args = (processId ,))
200- watching_thread .daemon = True
201- watching_thread .start ()
207+ else :
208+ threading .Timer (PARENT_PROCESS_WATCH_INTERVAL , watch_parent_process , args = [pid ]).start ()
202209
210+ self .watching_thread = threading .Thread (target = watch_parent_process , args = (processId ,))
211+ self .watching_thread .daemon = True
212+ self .watching_thread .start ()
203213 # Get our capabilities
204214 return {'capabilities' : self .capabilities ()}
205215
0 commit comments