Skip to content

Commit 65d6fd2

Browse files
deathaxeccordoba12
authored andcommitted
Fix parent process being killed on Windows when checking if it's alive (#445)
1 parent fed254e commit 65d6fd2

File tree

1 file changed

+43
-13
lines changed

1 file changed

+43
-13
lines changed

pyls/_utils.py

Lines changed: 43 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -147,19 +147,49 @@ def clip_column(column, lines, line_number):
147147
return min(column, max_column)
148148

149149

150-
def is_process_alive(pid):
151-
""" Check whether the process with the given pid is still alive.
150+
if os.name == 'nt':
151+
import ctypes
152152

153-
Args:
154-
pid (int): process ID
153+
kernel32 = ctypes.windll.kernel32
154+
PROCESS_QUERY_INFROMATION = 0x1000
155155

156-
Returns:
157-
bool: False if the process is not alive or don't have permission to check, True otherwise.
158-
"""
159-
try:
160-
os.kill(pid, 0)
161-
except OSError:
162-
# no such process or process is already dead
156+
def is_process_alive(pid):
157+
"""Check whether the process with the given pid is still alive.
158+
159+
Running `os.kill()` on Windows always exits the process, so it can't be used to check for an alive process.
160+
see: https://docs.python.org/3/library/os.html?highlight=os%20kill#os.kill
161+
162+
Hence ctypes is used to check for the process directly via windows API avoiding any other 3rd-party dependency.
163+
164+
Args:
165+
pid (int): process ID
166+
167+
Returns:
168+
bool: False if the process is not alive or don't have permission to check, True otherwise.
169+
"""
170+
process = kernel32.OpenProcess(PROCESS_QUERY_INFROMATION, 0, pid)
171+
if process != 0:
172+
kernel32.CloseHandle(process)
173+
return True
163174
return False
164-
else:
165-
return True
175+
176+
else:
177+
import errno
178+
179+
def is_process_alive(pid):
180+
"""Check whether the process with the given pid is still alive.
181+
182+
Args:
183+
pid (int): process ID
184+
185+
Returns:
186+
bool: False if the process is not alive or don't have permission to check, True otherwise.
187+
"""
188+
if pid < 0:
189+
return False
190+
try:
191+
os.kill(pid, 0)
192+
except OSError as e:
193+
return e.errno == errno.EPERM
194+
else:
195+
return True

0 commit comments

Comments
 (0)