@@ -34,18 +34,28 @@ def setup(self):
34
34
35
35
def handle (self ):
36
36
self .delegate .start ()
37
+ # pylint: disable=no-member
38
+ self .SHUTDOWN_CALL ()
37
39
38
40
39
41
def start_tcp_lang_server (bind_addr , port , check_parent_process , handler_class ):
40
42
if not issubclass (handler_class , PythonLanguageServer ):
41
43
raise ValueError ('Handler class must be an instance of PythonLanguageServer' )
42
44
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
+
43
52
# Construct a custom wrapper class around the user's handler_class
44
53
wrapper_class = type (
45
54
handler_class .__name__ + 'Handler' ,
46
55
(_StreamHandlerWrapper ,),
47
56
{'DELEGATE_CLASS' : partial (handler_class ,
48
- check_parent_process = check_parent_process )}
57
+ check_parent_process = check_parent_process ),
58
+ 'SHUTDOWN_CALL' : shutdown_server }
49
59
)
50
60
51
61
server = socketserver .TCPServer ((bind_addr , port ), wrapper_class )
@@ -78,6 +88,7 @@ def __init__(self, rx, tx, check_parent_process=False):
78
88
self .workspace = None
79
89
self .config = None
80
90
self .root_uri = None
91
+ self .watching_thread = None
81
92
self .workspaces = {}
82
93
self .uri_workspace_mapper = {}
83
94
@@ -187,19 +198,18 @@ def m_initialize(self, processId=None, rootUri=None, rootPath=None, initializati
187
198
self ._dispatchers = self ._hook ('pyls_dispatchers' )
188
199
self ._hook ('pyls_initialize' )
189
200
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 :
191
202
def watch_parent_process (pid ):
192
203
# exit when the given pid is not alive
193
204
if not _utils .is_process_alive (pid ):
194
205
log .info ("parent process %s is not alive" , pid )
195
206
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 ()
202
209
210
+ self .watching_thread = threading .Thread (target = watch_parent_process , args = (processId ,))
211
+ self .watching_thread .daemon = True
212
+ self .watching_thread .start ()
203
213
# Get our capabilities
204
214
return {'capabilities' : self .capabilities ()}
205
215
0 commit comments