passenger 4.0.42 → 4.0.43

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of passenger might be problematic. Click here for more details.

Files changed (67) hide show
  1. checksums.yaml +8 -8
  2. checksums.yaml.gz.asc +7 -7
  3. data.tar.gz.asc +7 -7
  4. data/CHANGELOG +13 -0
  5. data/CONTRIBUTING.md +2 -19
  6. data/build/agents.rb +4 -1
  7. data/build/cxx_tests.rb +7 -2
  8. data/build/debian.rb +1 -1
  9. data/debian.template/control.template +0 -2
  10. data/doc/CodingTipsAndPitfalls.md +56 -0
  11. data/doc/Users guide Apache.idmap.txt +16 -14
  12. data/doc/Users guide Nginx.idmap.txt +8 -6
  13. data/doc/Users guide Standalone.idmap.txt +3 -1
  14. data/doc/Users guide Standalone.txt +1 -1
  15. data/doc/users_guide_snippets/environment_variables.txt +1 -0
  16. data/doc/users_guide_snippets/installation.txt +5 -5
  17. data/doc/users_guide_snippets/support_information.txt +42 -9
  18. data/doc/users_guide_snippets/troubleshooting/default.txt +42 -0
  19. data/ext/common/ApplicationPool2/Common.h +1 -0
  20. data/ext/common/ApplicationPool2/DirectSpawner.h +2 -7
  21. data/ext/common/ApplicationPool2/DummySpawner.h +1 -1
  22. data/ext/common/ApplicationPool2/Group.h +4 -2
  23. data/ext/common/ApplicationPool2/Options.h +9 -7
  24. data/ext/common/ApplicationPool2/Pool.h +83 -40
  25. data/ext/common/ApplicationPool2/Process.h +2 -6
  26. data/ext/common/ApplicationPool2/README.md +0 -40
  27. data/ext/common/ApplicationPool2/SmartSpawner.h +2 -9
  28. data/ext/common/ApplicationPool2/Spawner.h +1 -4
  29. data/ext/common/ApplicationPool2/SpawnerFactory.h +6 -9
  30. data/ext/common/ApplicationPool2/SuperGroup.h +3 -3
  31. data/ext/common/Constants.h +1 -1
  32. data/ext/common/UnionStation/Connection.h +227 -0
  33. data/ext/common/UnionStation/Core.h +497 -0
  34. data/ext/common/UnionStation/ScopeLog.h +172 -0
  35. data/ext/common/UnionStation/Transaction.h +276 -0
  36. data/ext/common/Utils.cpp +83 -8
  37. data/ext/common/Utils.h +25 -4
  38. data/ext/common/Utils/AnsiColorConstants.h +1 -0
  39. data/ext/common/Utils/ProcessMetricsCollector.h +6 -170
  40. data/ext/common/Utils/SpeedMeter.h +258 -0
  41. data/ext/common/Utils/StrIntUtils.cpp +6 -0
  42. data/ext/common/Utils/StringScanning.h +277 -0
  43. data/ext/common/Utils/SystemMetricsCollector.h +1460 -0
  44. data/ext/common/agents/Base.cpp +8 -8
  45. data/ext/common/agents/HelperAgent/Main.cpp +12 -6
  46. data/ext/common/agents/HelperAgent/RequestHandler.h +15 -16
  47. data/ext/common/agents/HelperAgent/SystemMetricsTool.cpp +199 -0
  48. data/ext/common/agents/LoggingAgent/LoggingServer.h +2 -1
  49. data/ext/common/agents/SpawnPreparer.cpp +20 -32
  50. data/lib/phusion_passenger.rb +1 -1
  51. data/lib/phusion_passenger/config/list_instances_command.rb +118 -0
  52. data/lib/phusion_passenger/config/main.rb +22 -4
  53. data/lib/phusion_passenger/config/system_metrics_command.rb +37 -0
  54. data/lib/phusion_passenger/config/utils.rb +1 -1
  55. data/lib/phusion_passenger/loader_shared_helpers.rb +8 -5
  56. data/lib/phusion_passenger/platform_info/compiler.rb +1 -1
  57. data/resources/templates/error_layout.html.template +3 -3
  58. data/test/cxx/ApplicationPool2/DirectSpawnerTest.cpp +3 -5
  59. data/test/cxx/ApplicationPool2/PoolTest.cpp +1 -3
  60. data/test/cxx/ApplicationPool2/ProcessTest.cpp +4 -4
  61. data/test/cxx/ApplicationPool2/SmartSpawnerTest.cpp +5 -7
  62. data/test/cxx/RequestHandlerTest.cpp +9 -3
  63. data/test/cxx/UnionStationTest.cpp +61 -64
  64. metadata +13 -4
  65. metadata.gz.asc +7 -7
  66. data/ext/common/UnionStation.h +0 -968
  67. data/helper-scripts/system-memory-stats.py +0 -207
@@ -438,7 +438,7 @@ dumpFileDescriptorInfoWithLsof(AbortHandlerState &state, void *userData) {
438
438
  end = appendULL(end, state.pid);
439
439
  *end = '\0';
440
440
 
441
- closeAllFileDescriptors(2);
441
+ closeAllFileDescriptors(2, true);
442
442
 
443
443
  execlp("lsof", "lsof", "-p", state.messageBuf, "-nP", (const char * const) 0);
444
444
 
@@ -457,7 +457,7 @@ dumpFileDescriptorInfoWithLs(AbortHandlerState &state, char *end) {
457
457
 
458
458
  pid = asyncFork();
459
459
  if (pid == 0) {
460
- closeAllFileDescriptors(2);
460
+ closeAllFileDescriptors(2, true);
461
461
  // The '-v' is for natural sorting on Linux. On BSD -v means something else but it's harmless.
462
462
  execlp("ls", "ls", "-lv", state.messageBuf, (const char * const) 0);
463
463
  _exit(1);
@@ -517,7 +517,7 @@ dumpWithCrashWatch(AbortHandlerState &state) {
517
517
 
518
518
  pid_t child = asyncFork();
519
519
  if (child == 0) {
520
- closeAllFileDescriptors(2);
520
+ closeAllFileDescriptors(2, true);
521
521
  execlp("crash-watch", "crash-watch", "--dump", pidStr, (char * const) 0);
522
522
  if (errno == ENOENT) {
523
523
  safePrintErr("Crash-watch is not installed. Please install it with 'gem install crash-watch' "
@@ -583,7 +583,7 @@ dumpWithCrashWatch(AbortHandlerState &state) {
583
583
 
584
584
  close(p[1]);
585
585
  dup2(p[0], STDIN_FILENO);
586
- closeAllFileDescriptors(2);
586
+ closeAllFileDescriptors(2, true);
587
587
 
588
588
  char *command = end;
589
589
  end = appendText(end, "exec ");
@@ -664,7 +664,7 @@ dumpDiagnostics(AbortHandlerState &state) {
664
664
  // Dump human-readable time string and string.
665
665
  pid = asyncFork();
666
666
  if (pid == 0) {
667
- closeAllFileDescriptors(2);
667
+ closeAllFileDescriptors(2, true);
668
668
  execlp("date", "date", (const char * const) 0);
669
669
  _exit(1);
670
670
  } else if (pid == -1) {
@@ -676,7 +676,7 @@ dumpDiagnostics(AbortHandlerState &state) {
676
676
  // Dump system uname.
677
677
  pid = asyncFork();
678
678
  if (pid == 0) {
679
- closeAllFileDescriptors(2);
679
+ closeAllFileDescriptors(2, true);
680
680
  execlp("uname", "uname", "-mprsv", (const char * const) 0);
681
681
  _exit(1);
682
682
  } else if (pid == -1) {
@@ -688,7 +688,7 @@ dumpDiagnostics(AbortHandlerState &state) {
688
688
  // Dump ulimit.
689
689
  pid = asyncFork();
690
690
  if (pid == 0) {
691
- closeAllFileDescriptors(2);
691
+ closeAllFileDescriptors(2, true);
692
692
  execlp("ulimit", "ulimit", "-a", (const char * const) 0);
693
693
  // On Linux 'ulimit' is a shell builtin, not a command.
694
694
  execlp("/bin/sh", "/bin/sh", "-c", "ulimit -a", (const char * const) 0);
@@ -929,7 +929,7 @@ abortHandler(int signo, siginfo_t *info, void *ctx) {
929
929
 
930
930
  child = asyncFork();
931
931
  if (child == 0) {
932
- closeAllFileDescriptors(2);
932
+ closeAllFileDescriptors(2, true);
933
933
  #ifdef __APPLE__
934
934
  execlp("osascript", "osascript", "-e", "beep 2", (const char * const) 0);
935
935
  safePrintErr("Cannot execute 'osascript' command\n");
@@ -53,6 +53,7 @@
53
53
  #include <agents/HelperAgent/RequestHandler.h>
54
54
  #include <agents/HelperAgent/RequestHandler.cpp>
55
55
  #include <agents/HelperAgent/AgentOptions.h>
56
+ #include <agents/HelperAgent/SystemMetricsTool.cpp>
56
57
 
57
58
  #include <agents/Base.h>
58
59
  #include <Constants.h>
@@ -63,7 +64,7 @@
63
64
  #include <ResourceLocator.h>
64
65
  #include <BackgroundEventLoop.cpp>
65
66
  #include <ServerInstanceDir.h>
66
- #include <UnionStation.h>
67
+ #include <UnionStation/Core.h>
67
68
  #include <Exceptions.h>
68
69
  #include <MultiLibeio.cpp>
69
70
  #include <Utils.h>
@@ -261,7 +262,7 @@ private:
261
262
  FileDescriptor requestSocket;
262
263
  ServerInstanceDir serverInstanceDir;
263
264
  ServerInstanceDir::GenerationPtr generation;
264
- UnionStation::LoggerFactoryPtr loggerFactory;
265
+ UnionStation::CorePtr unionStationCore;
265
266
  RandomGeneratorPtr randomGenerator;
266
267
  SpawnerFactoryPtr spawnerFactory;
267
268
  PoolPtr pool;
@@ -459,11 +460,11 @@ public:
459
460
  }
460
461
 
461
462
  UPDATE_TRACE_POINT();
462
- loggerFactory = boost::make_shared<UnionStation::LoggerFactory>(options.loggingAgentAddress,
463
+ unionStationCore = boost::make_shared<UnionStation::Core>(options.loggingAgentAddress,
463
464
  "logging", options.loggingAgentPassword);
464
- spawnerFactory = boost::make_shared<SpawnerFactory>(poolLoop.safe,
465
- resourceLocator, generation, boost::make_shared<SpawnerConfig>(randomGenerator));
466
- pool = boost::make_shared<Pool>(spawnerFactory, loggerFactory,
465
+ spawnerFactory = boost::make_shared<SpawnerFactory>(resourceLocator,
466
+ generation, boost::make_shared<SpawnerConfig>(randomGenerator));
467
+ pool = boost::make_shared<Pool>(spawnerFactory, unionStationCore,
467
468
  randomGenerator, &options);
468
469
  pool->initialize();
469
470
  pool->setMax(options.maxPoolSize);
@@ -620,6 +621,11 @@ public:
620
621
  int
621
622
  main(int argc, char *argv[]) {
622
623
  TRACE_POINT();
624
+
625
+ if (argc > 1 && strcmp(argv[1], "system-metrics") == 0) {
626
+ return SystemMetricsTool::main(argc, argv);
627
+ }
628
+
623
629
  AgentOptionsPtr options;
624
630
  try {
625
631
  options = boost::make_shared<AgentOptions>(
@@ -133,7 +133,9 @@
133
133
  #include <EventedBufferedInput.h>
134
134
  #include <MessageReadersWriters.h>
135
135
  #include <Constants.h>
136
- #include <UnionStation.h>
136
+ #include <UnionStation/Core.h>
137
+ #include <UnionStation/Transaction.h>
138
+ #include <UnionStation/ScopeLog.h>
137
139
  #include <ApplicationPool2/Pool.h>
138
140
  #include <Utils/StrIntUtils.h>
139
141
  #include <Utils/IOUtils.h>
@@ -528,16 +530,16 @@ public:
528
530
  }
529
531
 
530
532
  bool useUnionStation() const {
531
- return options.logger != NULL;
533
+ return options.transaction != NULL;
532
534
  }
533
535
 
534
- UnionStation::LoggerPtr getLogger() const {
535
- return options.logger;
536
+ UnionStation::TransactionPtr getUnionStationTransaction() const {
537
+ return options.transaction;
536
538
  }
537
539
 
538
540
  void beginScopeLog(UnionStation::ScopeLog **scopeLog, const char *name) {
539
- if (options.logger != NULL) {
540
- *scopeLog = new UnionStation::ScopeLog(options.logger, name);
541
+ if (options.transaction != NULL) {
542
+ *scopeLog = new UnionStation::ScopeLog(options.transaction, name);
541
543
  }
542
544
  }
543
545
 
@@ -550,7 +552,7 @@ public:
550
552
  }
551
553
 
552
554
  void logMessage(const StaticString &message) {
553
- options.logger->message(message);
555
+ options.transaction->message(message);
554
556
  }
555
557
 
556
558
  void verifyInvariants() const {
@@ -617,16 +619,13 @@ public:
617
619
 
618
620
  private:
619
621
  friend class Client;
620
- typedef UnionStation::LoggerFactory LoggerFactory;
621
- typedef UnionStation::LoggerFactoryPtr LoggerFactoryPtr;
622
- typedef UnionStation::LoggerPtr LoggerPtr;
623
622
 
624
623
  const SafeLibevPtr libev;
625
624
  FileDescriptor requestSocket;
626
625
  PoolPtr pool;
627
626
  const AgentOptions &options;
628
627
  const ResourceLocator resourceLocator;
629
- LoggerFactoryPtr loggerFactory;
628
+ UnionStation::CorePtr unionStationCore;
630
629
  ev::io requestSocketWatcher;
631
630
  ev::timer resumeSocketWatcherTimer;
632
631
  HashMap<int, ClientPtr> clients;
@@ -1933,9 +1932,9 @@ private:
1933
1932
  return;
1934
1933
  }
1935
1934
 
1936
- client->options.logger = loggerFactory->newTransaction(
1935
+ client->options.transaction = unionStationCore->newTransaction(
1937
1936
  options.getAppGroupName(), "requests", key, filters);
1938
- if (!client->options.logger->isNull()) {
1937
+ if (!client->options.transaction->isNull()) {
1939
1938
  client->options.analytics = true;
1940
1939
  client->options.unionStationKey = key;
1941
1940
  }
@@ -2327,7 +2326,7 @@ private:
2327
2326
 
2328
2327
  if (client->options.analytics) {
2329
2328
  data.push_back(makeStaticStringWithNull("PASSENGER_TXN_ID"));
2330
- data.push_back(makeStaticStringWithNull(client->options.logger->getTxnId()));
2329
+ data.push_back(makeStaticStringWithNull(client->options.transaction->getTxnId()));
2331
2330
  }
2332
2331
 
2333
2332
  uint32_t dataSize = 0;
@@ -2402,7 +2401,7 @@ private:
2402
2401
 
2403
2402
  if (client->options.analytics) {
2404
2403
  data.append("Passenger-Txn-Id: ");
2405
- data.append(client->options.logger->getTxnId());
2404
+ data.append(client->options.transaction->getTxnId());
2406
2405
  data.append("\r\n");
2407
2406
  }
2408
2407
 
@@ -2614,7 +2613,7 @@ public:
2614
2613
  {
2615
2614
  accept4Available = true;
2616
2615
  connectPasswordTimeout = 15000;
2617
- loggerFactory = pool->loggerFactory;
2616
+ unionStationCore = pool->unionStationCore;
2618
2617
 
2619
2618
  requestSocketWatcher.set(_requestSocket, ev::READ);
2620
2619
  requestSocketWatcher.set(_libev->getLoop());
@@ -0,0 +1,199 @@
1
+ /*
2
+ * Phusion Passenger - https://www.phusionpassenger.com/
3
+ * Copyright (c) 2014 Phusion
4
+ *
5
+ * "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
6
+ *
7
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ * of this software and associated documentation files (the "Software"), to deal
9
+ * in the Software without restriction, including without limitation the rights
10
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ * copies of the Software, and to permit persons to whom the Software is
12
+ * furnished to do so, subject to the following conditions:
13
+ *
14
+ * The above copyright notice and this permission notice shall be included in
15
+ * all copies or substantial portions of the Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
+ * THE SOFTWARE.
24
+ */
25
+ #include <iostream>
26
+ #include <string>
27
+ #include <unistd.h>
28
+ #include <cstdio>
29
+ #include <cstring>
30
+ #include <Utils.h>
31
+ #include <Utils/StrIntUtils.h>
32
+ #include <Utils/SystemMetricsCollector.h>
33
+
34
+ namespace SystemMetricsTool {
35
+
36
+ using namespace std;
37
+ using namespace Passenger;
38
+
39
+ struct Options {
40
+ bool xml;
41
+ SystemMetrics::XmlOptions xmlOptions;
42
+ SystemMetrics::DescriptionOptions descOptions;
43
+ int interval;
44
+ bool stdin;
45
+ bool exitOnUnexpectedError;
46
+ bool help;
47
+
48
+ Options() {
49
+ xml = false;
50
+ descOptions.colors = isatty(1);
51
+ interval = -1;
52
+ stdin = false;
53
+ exitOnUnexpectedError = true;
54
+ help = false;
55
+ }
56
+ };
57
+
58
+ static bool
59
+ isFlag(const char *arg, char shortFlagName, const char *longFlagName) {
60
+ return strcmp(arg, longFlagName) == 0
61
+ || (shortFlagName != '\0' && arg[0] == '-'
62
+ && arg[1] == shortFlagName && arg[2] == '\0');
63
+ }
64
+
65
+ static void
66
+ usage() {
67
+ printf("Usage: passenger-config system-metrics [OPTIONS]\n");
68
+ printf("Displays various metrics about the system.\n");
69
+ printf("\n");
70
+ printf("Options:\n");
71
+ printf(" --xml Output in XML format\n");
72
+ printf(" --no-general Do not display general metrics\n");
73
+ printf(" --no-cpu Do not display CPU metrics\n");
74
+ printf(" --no-memory Do not display memory metrics\n");
75
+ printf(" --force-colors Display colors even if stdout is not a TTY\n");
76
+ printf(" -w --watch INTERVAL Reprint metrics every INTERVAL seconds\n");
77
+ printf(" --stdin Reprint metrics every time a newline is received on\n");
78
+ printf(" stdin, until EOF. Mutually exclusive with --watch\n");
79
+ printf(" --no-exit-on-unexpected-error Normally, if an unexpected error is\n");
80
+ printf(" encountered while collecting system metrics, this\n");
81
+ printf(" program will exit with an error code. This option\n");
82
+ printf(" suppresses that\n");
83
+ printf(" -h, --help Show this help\n");
84
+ }
85
+
86
+ static Options
87
+ parseOptions(int argc, char *argv[]) {
88
+ Options options;
89
+ int i = 2;
90
+
91
+ while (i < argc) {
92
+ if (isFlag(argv[i], '\0', "--xml")) {
93
+ options.xml = true;
94
+ i++;
95
+ } else if (isFlag(argv[i], '\0', "--no-general")) {
96
+ options.xmlOptions.general = false;
97
+ options.descOptions.general = false;
98
+ i++;
99
+ } else if (isFlag(argv[i], '\0', "--no-cpu")) {
100
+ options.xmlOptions.cpu = false;
101
+ options.descOptions.cpu = false;
102
+ i++;
103
+ } else if (isFlag(argv[i], '\0', "--no-memory")) {
104
+ options.xmlOptions.memory = false;
105
+ options.descOptions.memory = false;
106
+ i++;
107
+ } else if (isFlag(argv[i], '\0', "--force-colors")) {
108
+ options.descOptions.colors = true;
109
+ i++;
110
+ } else if (isFlag(argv[i], 'w', "--watch")) {
111
+ if (argc >= i + 2) {
112
+ options.interval = atoi(argv[i + 1]);
113
+ i += 2;
114
+ } else {
115
+ fprintf(stderr, "ERROR: extra argument required for --watch\n");
116
+ usage();
117
+ exit(1);
118
+ }
119
+ } else if (isFlag(argv[i], '\0', "--stdin")) {
120
+ options.stdin = true;
121
+ i++;
122
+ } else if (isFlag(argv[i], '\0', "--no-exit-on-unexpected-error")) {
123
+ options.exitOnUnexpectedError = false;
124
+ i++;
125
+ } else if (isFlag(argv[i], 'h', "--help")) {
126
+ options.help = true;
127
+ i++;
128
+ } else {
129
+ fprintf(stderr, "ERROR: unrecognized argument %s\n", argv[i]);
130
+ usage();
131
+ exit(1);
132
+ }
133
+ }
134
+ if (options.interval != -1 && options.stdin) {
135
+ fprintf(stderr, "ERROR: --watch and --stdin are mutually exclusive.\n");
136
+ exit(1);
137
+ }
138
+ return options;
139
+ }
140
+
141
+ static bool
142
+ waitForNextLine() {
143
+ char buf[1024];
144
+ return fgets(buf, sizeof(buf), stdin) != NULL;
145
+ }
146
+
147
+ static void
148
+ perform(const Options &options, SystemMetricsCollector &collector, SystemMetrics &metrics) {
149
+ try {
150
+ collector.collect(metrics);
151
+ if (options.xml) {
152
+ cout << "<?xml version=\"1.0\" encoding=\"utf-8\"?>";
153
+ metrics.toXml(cout, options.xmlOptions);
154
+ cout << endl;
155
+ } else {
156
+ metrics.toDescription(cout, options.descOptions);
157
+ }
158
+ } catch (const RuntimeException &e) {
159
+ fprintf(stderr, "An error occurred while collecting system metrics: %s\n", e.what());
160
+ if (options.exitOnUnexpectedError) {
161
+ exit(1);
162
+ }
163
+ }
164
+ }
165
+
166
+ static int
167
+ main(int argc, char *argv[]) {
168
+ Options options = parseOptions(argc, argv);
169
+ if (options.help) {
170
+ usage();
171
+ return 0;
172
+ }
173
+
174
+ SystemMetricsCollector collector;
175
+ SystemMetrics metrics;
176
+
177
+ if (options.descOptions.cpu) {
178
+ collector.collect(metrics);
179
+ // We have to measure system metrics within an interval
180
+ // in order to determine the CPU usage.
181
+ usleep(50000);
182
+ }
183
+
184
+ if (options.stdin) {
185
+ while (waitForNextLine()) {
186
+ perform(options, collector, metrics);
187
+ }
188
+ } else {
189
+ do {
190
+ perform(options, collector, metrics);
191
+ if (options.interval != -1) {
192
+ sleep(options.interval);
193
+ }
194
+ } while (options.interval != -1);
195
+ }
196
+ return 0;
197
+ }
198
+
199
+ } // namespace SystemMetricsTool
@@ -534,7 +534,8 @@ private:
534
534
  }
535
535
 
536
536
  bool supportedCategory(const StaticString &category) const {
537
- return category == "requests" || category == "processes" || category == "exceptions";
537
+ return category == "requests" || category == "processes"
538
+ || category == "exceptions" || category == "system_metrics";
538
539
  }
539
540
 
540
541
  LogSinkPtr openLogFile() {
@@ -41,6 +41,8 @@
41
41
  #include <unistd.h>
42
42
  #include <stdlib.h>
43
43
  #include <string>
44
+ #include <sstream>
45
+ #include <Utils/SystemMetricsCollector.h>
44
46
  #include <Utils/Base64.h>
45
47
 
46
48
  using namespace std;
@@ -148,42 +150,28 @@ dumpInformation() {
148
150
  fclose(f);
149
151
  }
150
152
 
151
- f = fopen((dir + "/ulimit").c_str(), "w");
152
- if (f != NULL) {
153
- pid_t pid = fork();
154
- if (pid == 0) {
155
- dup2(fileno(f), 1);
156
- execlp("ulimit", "ulimit", "-a", (char *) 0);
157
- _exit(1);
158
- } else if (pid == -1) {
159
- int e = errno;
160
- fprintf(stderr, "Error: cannot fork a new process: %s (errno=%d)\n",
161
- strerror(e), e);
162
- } else {
163
- waitpid(pid, NULL, 0);
164
- }
165
- fclose(f);
153
+ SystemMetrics metrics;
154
+ bool collected = false;
155
+ try {
156
+ SystemMetricsCollector collector;
157
+ collector.collect(metrics);
158
+ usleep(50000); // Correct collect CPU metrics.
159
+ collector.collect(metrics);
160
+ collected = true;
161
+ } catch (const RuntimeException &e) {
162
+ fprintf(stderr, "Warning: %s\n", e.what());
166
163
  }
167
-
168
- #ifdef __linux__
169
- // TODO: call helper-scripts/system-memory-stats.py
170
- f = fopen((dir + "/sysmemory").c_str(), "w");
164
+ if (collected) {
165
+ f = fopen((dir + "/system_metrics").c_str(), "w");
171
166
  if (f != NULL) {
172
- pid_t pid = fork();
173
- if (pid == 0) {
174
- dup2(fileno(f), 1);
175
- execlp("free", "free", "-m", (char *) 0);
176
- _exit(1);
177
- } else if (pid == -1) {
178
- int e = errno;
179
- fprintf(stderr, "Error: cannot fork a new process: %s (errno=%d)\n",
180
- strerror(e), e);
181
- } else {
182
- waitpid(pid, NULL, 0);
183
- }
167
+ stringstream stream;
168
+ metrics.toDescription(stream);
169
+ string info = stream.str();
170
+
171
+ fwrite(info.data(), 1, info.size(), f);
184
172
  fclose(f);
185
173
  }
186
- #endif
174
+ }
187
175
  }
188
176
 
189
177
  // Usage: SpawnPreparer <working directory> <envvars> <executable> <exec args...>