You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: guides/getting-started/readme.md
+25-10Lines changed: 25 additions & 10 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -39,6 +39,25 @@ container.wait
39
39
Console.debug "Finished."
40
40
```
41
41
42
+
### Stopping Child Processes
43
+
44
+
Containers provide three approaches for stopping child processes (or threads). When you call `container.stop()`, a progressive approach is used:
45
+
46
+
-**Interrupt** means **"Please start shutting down gracefully"**. This is the gentlest shutdown request, giving applications maximum time to finish current work and cleanup resources.
47
+
48
+
-**Terminate** means **"Shut down now"**. This is more urgent - the process should stop what it's doing and terminate promptly, but still has a chance to cleanup.
49
+
50
+
-**Kill** means **"Die immediately"**. This forcefully terminates the process with no cleanup opportunity. This is the method of last resort.
51
+
52
+
The escalation sequence follows this pattern:
53
+
1. interrupt → wait for timeout → still running?
54
+
2. terminate → wait for timeout → still running?
55
+
3. kill → process terminated.
56
+
57
+
This gives well-behaved processes multiple opportunities to shut down gracefully, while ensuring that unresponsive processes are eventually killed.
58
+
59
+
**Implementation Note:** For forked containers, these methods send Unix signals (`SIGINT`, `SIGTERM`, `SIGKILL`). For threaded containers, they use different mechanisms appropriate to threads. The container abstraction hides these implementation details.
60
+
42
61
## Controllers
43
62
44
63
The controller provides the life-cycle management for one or more containers of processes. It provides behaviour like starting, restarting, reloading and stopping. You can see some [example implementations in Falcon](https://github.com/socketry/falcon/blob/master/lib/falcon/controller/). If the process running the controller receives `SIGHUP` it will recreate the container gracefully.
@@ -72,16 +91,12 @@ controller.run
72
91
# If you send SIGHUP to this process, it will recreate the container.
73
92
```
74
93
75
-
## Signal Handling
76
-
77
-
`SIGINT` is the reload signal. You may send this to a program to request that it reload its configuration. The default behavior is to gracefully reload the container.
78
-
79
-
`SIGINT` is the interrupt signal. The terminal sends it to the foreground process when the user presses **ctrl-c**. The default behavior is to terminate the process, but it can be caught or ignored. The intention is to provide a mechanism for an orderly, graceful shutdown.
80
-
81
-
`SIGQUIT` is the dump core signal. The terminal sends it to the foreground process when the user presses **ctrl-\\**. The default behavior is to terminate the process and dump core, but it can be caught or ignored. The intention is to provide a mechanism for the user to abort the process. You can look at `SIGINT` as "user-initiated happy termination" and `SIGQUIT` as "user-initiated unhappy termination."
94
+
### Controller Signal Handling
82
95
83
-
`SIGTERM` is the termination signal. The default behavior is to terminate the process, but it also can be caught or ignored. The intention is to kill the process, gracefully or not, but to first allow it a chance to cleanup.
96
+
Controllers are designed to run at the process level and are therefore responsible for processing signals. When your controller process receives these signals:
84
97
85
-
`SIGKILL` is the kill signal. The only behavior is to kill the process, immediately. As the process cannot catch the signal, it cannot cleanup, and thus this is a signal of last resort.
98
+
-`SIGHUP` → Gracefully reload the container (restart with new configuration).
99
+
-`SIGINT` → Begin graceful shutdown of the entire controller and all children.
100
+
-`SIGTERM` → Begin immediate shutdown of the controller and all children.
86
101
87
-
`SIGSTOP` is the pause signal. The only behavior is to pause the process; the signal cannot be caught or ignored. The shell uses pausing (and its counterpart, resuming via `SIGCONT`) to implement job control.
102
+
Ideally, do not send `SIGKILL` to a controller, as it will immediately terminate the controller without giving it a chance to gracefully shut down child processes. This can leave orphaned processes running and prevent proper cleanup.
Copy file name to clipboardExpand all lines: releases.md
+12Lines changed: 12 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,5 +1,17 @@
1
1
# Releases
2
2
3
+
## Unreleased
4
+
5
+
### Production Reliability Improvements
6
+
7
+
This release significantly improves container reliability by eliminating production hangs caused by unresponsive child processes.
8
+
9
+
**SIGKILL Fallback Support**: Containers now automatically escalate to SIGKILL when child processes ignore SIGINT and SIGTERM signals. This prevents the critical production issue where containers would hang indefinitely waiting for uncooperative processes to exit.
10
+
11
+
**Hang Prevention**: Individual child processes now have timeout-based hang prevention. If a process closes its notification pipe but doesn't actually exit, the container will detect this and escalate to SIGKILL after a reasonable timeout instead of hanging forever.
12
+
13
+
**Improved Three-Phase Shutdown**: The `Group#stop()` method now uses a cleaner interrupt → terminate → kill escalation sequence with configurable timeouts for each phase, giving well-behaved processes multiple opportunities to shut down gracefully while ensuring unresponsive processes are eventually terminated.
14
+
3
15
## v0.25.0
4
16
5
17
- Introduce `async:container:notify:log:ready?` task for detecting process readiness.
0 commit comments