Skip to content

Commit

Permalink
Fix _storage_main terminate_on_parent_death not working on mac
Browse files Browse the repository at this point in the history
Prior to this commit, the `terminate_on_parent_death` function was only usable on linux, due to it using the prctl command.
This commit creates a new thread which polls the parent process, and signals terminate when it can no longer find the parent.
  • Loading branch information
jonathan-eq committed Oct 31, 2024
1 parent 97478fa commit 91e15dc
Showing 1 changed file with 23 additions and 23 deletions.
46 changes: 23 additions & 23 deletions src/ert/services/_storage_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
import signal
import socket
import string
import sys
import threading
import time
import warnings
from typing import Any, Dict, List, Optional, Union

Expand Down Expand Up @@ -123,30 +124,21 @@ def run_server(args: Optional[argparse.Namespace] = None, debug: bool = False) -
server.run(sockets=[sock])


def terminate_on_parent_death() -> None:
"""Quit the server when the parent does a SIGABRT or is otherwise destroyed.
This functionality has existed on Linux for a good while, but it isn't
exposed in the Python standard library. Use ctypes to hook into the
functionality.
def terminate_on_parent_death(stopped: threading.Event, poll_interval=1.0) -> None:

Check failure on line 127 in src/ert/services/_storage_main.py

View workflow job for this annotation

GitHub Actions / type-checking (3.12)

Function is missing a type annotation for one or more arguments
"""
Quit the server when the parent process is no longer running.
"""
if sys.platform != "linux" or "ERT_COMM_FD" not in os.environ:
return

from ctypes import CDLL, c_int, c_ulong # noqa: PLC0415

lib = CDLL(None)

# from <sys/prctl.h>
# int prctl(int option, ...)
prctl = lib.prctl
prctl.restype = c_int
prctl.argtypes = (c_int, c_ulong)
def check_parent_alive():

Check failure on line 132 in src/ert/services/_storage_main.py

View workflow job for this annotation

GitHub Actions / type-checking (3.12)

Function is missing a return type annotation
return os.getppid() != 1

# from <linux/prctl.h>
PR_SET_PDEATHSIG = 1
while check_parent_alive():

Check failure on line 135 in src/ert/services/_storage_main.py

View workflow job for this annotation

GitHub Actions / type-checking (3.12)

Call to untyped function "check_parent_alive" in typed context
if stopped.is_set():
return
time.sleep(poll_interval)

# connect parent death signal to our SIGTERM
prctl(PR_SET_PDEATHSIG, signal.SIGTERM)
# Parent is no longer alive, terminate this process.
os.kill(os.getpid(), signal.SIGTERM)


if __name__ == "__main__":
Expand All @@ -156,6 +148,14 @@ def terminate_on_parent_death() -> None:
warnings.filterwarnings("ignore", category=DeprecationWarning)
uvicorn.config.LOGGING_CONFIG.clear()
uvicorn.config.LOGGING_CONFIG.update(logging_conf)
terminate_on_parent_death()
_stopped = threading.Event()
terminate_on_parent_death_thread = threading.Thread(
target=terminate_on_parent_death, args=[_stopped, 1.0]
)
with ErtPluginContext(logger=logging.getLogger()) as context:
run_server(debug=False)
terminate_on_parent_death_thread.start()
try:
run_server(debug=False)
finally:
_stopped.set()
terminate_on_parent_death_thread.join()

0 comments on commit 91e15dc

Please sign in to comment.