1 /**
2  * ae.sys.process
3  *
4  * License:
5  *   This Source Code Form is subject to the terms of
6  *   the Mozilla Public License, v. 2.0. If a copy of
7  *   the MPL was not distributed with this file, You
8  *   can obtain one at http://mozilla.org/MPL/2.0/.
9  *
10  * Authors:
11  *   Vladimir Panteleev <vladimir@thecybershadow.net>
12  */
13 
14 module ae.sys.process;
15 
16 version(Posix):
17 
18 import ae.net.sync;
19 import ae.sys.signals;
20 
21 import std.process;
22 
23 /// Asynchronously wait for a process to terminate.
24 void asyncWait(Pid pid, void delegate(int status) dg)
25 {
26 	auto anchor = new ThreadAnchor;
27 
28 	void handler() nothrow @nogc
29 	{
30 		anchor.runAsync(
31 			{
32 				// Linux may coalesce multiple SIGCHLD into one, so
33 				// we need to explicitly check if our process exited.
34 				auto result = tryWait(pid);
35 				if (result.terminated)
36 				{
37 					removeSignalHandler(SIGCHLD, &handler);
38 					dg(result.status);
39 				}
40 			});
41 	}
42 
43 	addSignalHandler(SIGCHLD, &handler);
44 }
45 
46 version(unittest) import ae.sys.timing, ae.net.asockets;
47 
48 unittest
49 {
50 	string order;
51 
52 	auto pid = spawnProcess(["sleep", "1"]);
53 	asyncWait(pid, (int status) { assert(status == 0); order ~= "b"; });
54 	setTimeout({ order ~= "a"; },  500.msecs);
55 	setTimeout({ order ~= "c"; }, 1500.msecs);
56 	socketManager.loop();
57 
58 	assert(order == "abc");
59 }