1 module process_stats;
2 
3 import core.time;
4 
5 struct Stats {
6     int exitCode;
7     TickDuration totalTime;
8     ulong maxMemKB;
9 }
10 
11 version (linux) {
12     import core.sys.posix.sys.resource;
13     extern(C) pid_t wait4(pid_t pid, int* status, int options, rusage* rusage);
14 
15     Stats executeWithStats(alias spawnFunc, SpawnArgs...)(SpawnArgs spawnArgs) {
16         import core.stdc.errno;
17         import core.sys.posix.sys.wait;
18         import std.datetime;
19         import std.exception;
20 
21         Stats result;
22 
23         auto sw = StopWatch(AutoStart.yes);
24         auto pid = spawnFunc(spawnArgs).processID();
25         enforce(pid != -2);
26 
27         rusage usage;
28         while (true) {
29             int status;
30             auto check = wait4(pid, &status, 0, &usage);
31 
32             if (check == -1) {
33                 assert(errno == EINTR);
34                 continue;
35             }
36 
37             if (WIFEXITED(status)) {
38                 result.exitCode = WEXITSTATUS(status);
39                 break;
40             } else if (WIFSIGNALED(status)) {
41                 result.exitCode = -WTERMSIG(status);
42                 break;
43             }
44         }
45 
46         sw.stop();
47         result.totalTime = sw.peek();
48 
49         result.maxMemKB = usage.ru_maxrss;
50         enforce(result.maxMemKB != 0,
51             "Could not determine memory usage, kernel older than 2.6.32?");
52 
53         return result;
54     }
55 
56 } else {
57     static assert(0, "Platform not yet supported.");
58 }