Skip to content

Commit

Permalink
oslayer/winkeyboardcontrol: fix capture process termination
Browse files Browse the repository at this point in the history
The heartbeat thread needs to be stopped before exit, or with Python 3
the process will deadlock at exit trying to join it.
  • Loading branch information
benoit-pierre committed Aug 1, 2016
1 parent a0b9d52 commit b436d26
Showing 1 changed file with 17 additions and 7 deletions.
24 changes: 17 additions & 7 deletions plover/oslayer/winkeyboardcontrol.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
import multiprocessing
import os
import threading
import time

from ctypes import windll, wintypes

Expand Down Expand Up @@ -150,12 +149,18 @@ def __init__(self, ppid, atexit):
super(HeartBeat, self).__init__()
self._ppid = ppid
self._atexit = atexit
self._finished = threading.Event()

def run(self):
while pid_exists(self._ppid):
time.sleep(1)
if self._finished.wait(1):
break
self._atexit()

def stop(self):
self._finished.set()
self.join()


class KeyboardCaptureProcess(multiprocessing.Process):

Expand Down Expand Up @@ -221,7 +226,7 @@ def _open_key(rights):

def run(self):

heartbeat = HeartBeat(self._ppid, self.stop)
heartbeat = HeartBeat(self._ppid, self._send_quit)
heartbeat.start()

import atexit
Expand Down Expand Up @@ -292,16 +297,21 @@ def low_level_handler(code, wparam, lparam):
windll.user32.TranslateMessage(ctypes.byref(msg))
windll.user32.DispatchMessageW(ctypes.byref(msg))

heartbeat.stop()

def _send_quit(self):
windll.user32.PostThreadMessageW(self._tid,
0x0012, # WM_QUIT
0, 0)

def start(self):
self.daemon = True
super(KeyboardCaptureProcess, self).start()
self._tid = self._queue.get()

def stop(self):
if self.is_alive():
windll.user32.PostThreadMessageW(self._tid,
0x0012, # WM_QUIT
0, 0)
self._send_quit()
self.join()
# Wake up capture thread, so it gets a chance to check if it must stop.
self._queue.put((None, None))
Expand Down Expand Up @@ -341,9 +351,9 @@ def run(self):
(self.key_down if pressed else self.key_up)(key)

def cancel(self):
self._finished.set()
self._proc.stop()
if self.is_alive():
self._finished.set()
self.join()

def suppress_keyboard(self, suppressed_keys=()):
Expand Down

0 comments on commit b436d26

Please sign in to comment.