@@ -15,10 +15,10 @@ as [Streams](https://github.com/reactphp/stream).
1515
1616* [ Quickstart example] ( #quickstart-example )
1717* [ Processes] ( #processes )
18- * [ EventEmitter Events] ( #eventemitter-events )
1918 * [ Methods] ( #methods )
2019 * [ Stream Properties] ( #stream-properties )
2120 * [ Command] ( #command )
21+ * [ Termination] ( #termination )
2222 * [ Sigchild Compatibility] ( #sigchild-compatibility )
2323 * [ Windows Compatibility] ( #windows-compatibility )
2424* [ Install] ( #install )
@@ -48,11 +48,6 @@ See also the [examples](examples).
4848
4949## Processes
5050
51- ### EventEmitter Events
52-
53- * ` exit ` : Emitted whenever the process is no longer running. Event listeners
54- will receive the exit code and termination signal as two arguments.
55-
5651### Methods
5752
5853* ` start() ` : Launches the process and registers its IO streams with the event
@@ -205,6 +200,103 @@ the wrapping shell.
205200If you want to pass an invidual command only, you MAY want to consider
206201prepending the command string with ` exec ` to avoid the wrapping shell.
207202
203+ ### Termination
204+
205+ The ` exit ` event will be emitted whenever the process is no longer running.
206+ Event listeners will receive the exit code and termination signal as two
207+ arguments:
208+
209+ ``` php
210+ $process = new Process('sleep 10');
211+ $process->start($loop);
212+
213+ $process->on('exit', function ($code, $term) {
214+ if ($term === null) {
215+ echo 'exit with code ' . $code . PHP_EOL;
216+ } else {
217+ echo 'terminated with signal ' . $term . PHP_EOL;
218+ }
219+ });
220+ ```
221+
222+ Note that ` $code ` is ` null ` if the process has terminated, but the exit
223+ code could not be determined (for example
224+ [ sigchild compatibility] ( #sigchild-compatibility ) was disabled).
225+ Similarly, ` $term ` is ` null ` unless the process has terminated in response to
226+ an uncaught signal sent to it.
227+ This is not a limitation of this project, but actual how exit codes and signals
228+ are exposed on POSIX systems, for more details see also
229+ [ here] ( https://unix.stackexchange.com/questions/99112/default-exit-code-when-process-is-terminated ) .
230+
231+ It's also worth noting that process termination depends on all file descriptors
232+ being closed beforehand.
233+ This means that all [ process pipes] ( #stream-properties ) will emit a ` close `
234+ event before the ` exit ` event and that no more ` data ` events will arrive after
235+ the ` exit ` event.
236+ Accordingly, if either of these pipes is in a paused state (` pause() ` method
237+ or internally due to a ` pipe() ` call), this detection may not trigger.
238+
239+ The ` terminate(?int $signal = null): bool ` method can be used to send the
240+ process a signal (SIGTERM by default).
241+ Depending on which signal you send to the process and whether it has a signal
242+ handler registered, this can be used to either merely signal a process or even
243+ forcefully terminate it.
244+
245+ ``` php
246+ $process->terminate(SIGUSR1);
247+ ```
248+
249+ Keep the above section in mind if you want to forcefully terminate a process.
250+ If your process spawn sub-processes or implicitly uses the
251+ [ wrapping shell mentioned above] ( #command ) , its file descriptors may be
252+ inherited to child processes and terminating the main process may not
253+ necessarily terminate the whole process tree.
254+ It is highly suggested that you explicitly ` close() ` all process pipes
255+ accordingly when terminating a process:
256+
257+ ``` php
258+ $process = new Process('sleep 10');
259+ $process->start($loop);
260+
261+ $loop->addTimer(2.0, function () use ($process) {
262+ $process->stdin->close();
263+ $process->stout->close();
264+ $process->stderr->close();
265+ $process->terminate(SIGKILL);
266+ });
267+ ```
268+
269+ For many simple programs these seamingly complicated steps can also be avoided
270+ by prefixing the command line with ` exec ` to avoid the wrapping shell and its
271+ inherited process pipes as [ mentioned above] ( #command ) .
272+
273+ ``` php
274+ $process = new Process('exec sleep 10');
275+ $process->start($loop);
276+
277+ $loop->addTimer(2.0, function () use ($process) {
278+ $process->terminate();
279+ });
280+ ```
281+
282+ Many command line programs also wait for data on ` STDIN ` and terminate cleanly
283+ when this pipe is closed.
284+ For example, the following can be used to "soft-close" a ` cat ` process:
285+
286+ ``` php
287+ $process = new Process('cat');
288+ $process->start($loop);
289+
290+ $loop->addTimer(2.0, function () use ($process) {
291+ $process->stdin->end();
292+ });
293+ ```
294+
295+ While process pipes and termination may seem confusing to newcomers, the above
296+ properties actually allow some fine grained control over process termination,
297+ such as first trying a soft-close and then applying a force-close after a
298+ timeout.
299+
208300### Sigchild Compatibility
209301
210302When PHP has been compiled with the ` --enabled-sigchild ` option, a child
0 commit comments