From c11999499e6f9679da0272d96a1422025bbc0502 Mon Sep 17 00:00:00 2001 From: Romain Marcadier Date: Wed, 14 Oct 2020 12:18:16 +0200 Subject: [PATCH] fix(python): leftover jsii-kernel-* directories in TMPDIR (#2100) The Python runtime did not properly signal shutdown to the `node` process hosting the *jsii kernel*, causing it to be abruptly killed on Python interpreter exit. This means the *jsii kernel*'s own clean-up code was not allowed to run. This adds an `atexit` hook which will properly close the `node` process' `STDIN` file descriptor, effectively signaling it should shut down. This then gives the process 5 seconds to clean up after itself and finish before sending it `SIGTERM` (at which point it is given 5 seconds to terminate after which it will be terminated). --- .../src/jsii/_kernel/providers/process.py | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/packages/@jsii/python-runtime/src/jsii/_kernel/providers/process.py b/packages/@jsii/python-runtime/src/jsii/_kernel/providers/process.py index 5322066852..fa72285628 100644 --- a/packages/@jsii/python-runtime/src/jsii/_kernel/providers/process.py +++ b/packages/@jsii/python-runtime/src/jsii/_kernel/providers/process.py @@ -1,3 +1,4 @@ +import atexit import datetime import contextlib import enum @@ -275,16 +276,26 @@ def start(self): stdout=subprocess.PIPE, env=environ, ) + + # Clean this process up at exit, so it terminates "gracefully" + atexit.register(self.stop) + self.handshake() def stop(self): - # TODO: We can write an empty string here instead? - self._process.terminate() + # This process is closing already, un-registering the hook to not fire twice + atexit.unregister(self.stop) + + # Close the process' STDIN, singalling we are done with it + self._process.stdin.close() try: self._process.wait(timeout=5) except subprocess.TimeoutExpired: - self._process.kill() + try: + self._process.terminate(timeout=5) + except subprocess.TimeoutExpired: + self._process.kill() self._ctx_stack.close()