Prevent spurious /dev/shm/PostgreSQL.* files in tests
By default the postgres server uses `shm_open(3)` to create shared
memory to talk between workers. This means files directly inside of
`/dev/shm`. Since that directory is one of the few (maybe only?)
world-writeable and non-sandboxed directories, that means the server
can leave behind these useless files.
I investigated switching postgres to use the `sysv` mechanism for IPC,
but that doesn't really help us here. That just creates shared memory
segments that are even harder to track and clean up after a run.
For example:
https://www.ibm.com/docs/en/aix/7.2?topic=s-shmget-subroutine
> Once created, a shared memory segment is deleted only when the
> system reboots or by issuing the ipcrm command or using the following
> shmctl subroutine:
The final approach here is to make the test framework properly shut
down the various servers. It currently just expects the bazel sandbox
to kill the servers. I couldn't find a way to get node to
synchronously shut down the servers and wait for them to finish
shutting down. All node APIs I could find for this are asynchronous.
Those APIs cannot be used in node's `exit` hook, unfortunately. To
that end I wrote a node binding for the `waitpid(2)` syscall. This
forces node to wait for the servers to shut down before exiting the
test. This means we don't leave spurious files behind at the end of
the test in normal circumstances.
After this patch, I don't see any spurious files left behind anymore.
$ bazel test --runs_per_test=40 //scouting:scouting_test_chromium-local
Signed-off-by: Philipp Schrader <philipp.schrader@gmail.com>
Change-Id: Id798a1339cf4076c82bf31b94cc972476b57850b
diff --git a/scouting/testing/scouting_test_servers.py b/scouting/testing/scouting_test_servers.py
index 7a0d3c5..b6e5c7a 100644
--- a/scouting/testing/scouting_test_servers.py
+++ b/scouting/testing/scouting_test_servers.py
@@ -105,6 +105,13 @@
except FileNotFoundError:
pass
+def discard_signal(signum, frame):
+ """A NOP handler to ignore certain signals.
+
+ We use signal.pause() to wait for a signal. That means we can't use the default handler. The
+ default handler would tear the application down without stopping child processes.
+ """
+ pass
def main(argv: List[str]):
parser = argparse.ArgumentParser()
@@ -115,6 +122,8 @@
runner.start(args.port)
# Wait until we're asked to shut down via CTRL-C or SIGTERM.
+ signal.signal(signal.SIGINT, discard_signal)
+ signal.signal(signal.SIGTERM, discard_signal)
signal.pause()
runner.stop()