Shared memory leaks during rapid nodewebkit process restarts
26.5K reputation · 25 Jun 2023, 02:30 UTC
nodewebkit utilizes a child-process architecture to isolate the WebKit engine from the Node.js parent process. While this prevents a renderer crash from terminating the entire application, the library relies on shared memory buffers for data transfer between the environments.
When performing rapid-cycle restarts or interrupted upgrades, there is an indication that these shared buffers may not be consistently deallocated. Because the library lacks a built-in atomic rollback or cleanup mechanism for the underlying WebKit binaries, interrupted cycles can leave behind corrupted state files or leaked memory segments.
Does nodewebkit guarantee the full deallocation of shared memory buffers when a child process is terminated abruptly? Is there a documented method to manually trigger a cleanup of these buffers after a failed upgrade attempt?
1 answer
1 question comment
Use comments to ask for clarification. Post a solution as an answer.
2,340 reputation · 25 Jun 2023, 08:47 UTC
One thing worth adding to the mitigation list: the leak is often amplified by the relaunch logic, not just the abrupt kill. If your restart loop spawns a new nw.js instance before the old process has fully exited, the two overlap on the same user-data directory lock and on shared-memory allocation, which both leaks more segments and can leave the new instance failing to start or rendering blank.
A pattern that has worked reliably in practice:
- Send SIGTERM (or
taskkillwithout/F) and wait for the child processexitevent before spawning the replacement. - Only escalate to SIGKILL after a timeout (a few seconds is usually enough for Chromium's teardown to unlink its segments).
- Give each instance a unique
--user-data-dirso a slow shutdown never blocks the next launch on the profile lock — though note this avoids contention, it does not free already-orphaned segments.
To confirm the graceful path actually helps on your nw.js version, run ~100 kill -9 cycles and compare ipcs -m / /dev/shm usage, then repeat with the SIGTERM-and-wait flow. Behavior varies by Chromium version and OS, so verify against the exact build you ship.