1
0

cmUVProcessChain.cxx 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739
  1. /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
  2. file Copyright.txt or https://cmake.org/licensing for details. */
  3. #include "cmUVProcessChain.h"
  4. #include <array>
  5. #include <csignal>
  6. #include <cstdio>
  7. #include <istream> // IWYU pragma: keep
  8. #include <utility>
  9. #include <cm/memory>
  10. #include <cm3p/uv.h>
  11. #include "cm_fileno.hxx"
  12. #include "cmGetPipes.h"
  13. #include "cmUVHandlePtr.h"
  14. struct cmUVProcessChain::InternalData
  15. {
  16. struct StreamData
  17. {
  18. int BuiltinStream = -1;
  19. uv_stdio_container_t Stdio;
  20. };
  21. struct ProcessData
  22. {
  23. cmUVProcessChain::InternalData* Data;
  24. cm::uv_process_ptr Process;
  25. cm::uv_pipe_ptr InputPipe;
  26. cm::uv_pipe_ptr OutputPipe;
  27. Status ProcessStatus;
  28. void Finish();
  29. };
  30. cmUVProcessChainBuilder const* Builder = nullptr;
  31. bool Valid = false;
  32. cm::uv_loop_ptr BuiltinLoop;
  33. uv_loop_t* Loop;
  34. StreamData InputStreamData;
  35. StreamData OutputStreamData;
  36. StreamData ErrorStreamData;
  37. cm::uv_pipe_ptr TempOutputPipe;
  38. cm::uv_pipe_ptr TempErrorPipe;
  39. unsigned int ProcessesCompleted = 0;
  40. std::vector<std::unique_ptr<ProcessData>> Processes;
  41. bool Prepare(cmUVProcessChainBuilder const* builder);
  42. void SpawnProcess(
  43. std::size_t index,
  44. cmUVProcessChainBuilder::ProcessConfiguration const& config, bool first,
  45. bool last);
  46. void Finish();
  47. };
  48. cmUVProcessChainBuilder::cmUVProcessChainBuilder() = default;
  49. cmUVProcessChainBuilder& cmUVProcessChainBuilder::AddCommand(
  50. std::vector<std::string> arguments)
  51. {
  52. if (!arguments.empty()) {
  53. this->Processes.emplace_back();
  54. this->Processes.back().Arguments = std::move(arguments);
  55. }
  56. return *this;
  57. }
  58. cmUVProcessChainBuilder& cmUVProcessChainBuilder::SetBuiltinLoop()
  59. {
  60. this->Loop = nullptr;
  61. return *this;
  62. }
  63. cmUVProcessChainBuilder& cmUVProcessChainBuilder::SetExternalLoop(
  64. uv_loop_t& loop)
  65. {
  66. this->Loop = &loop;
  67. return *this;
  68. }
  69. cmUVProcessChainBuilder& cmUVProcessChainBuilder::SetNoStream(Stream stdio)
  70. {
  71. switch (stdio) {
  72. case Stream_INPUT:
  73. case Stream_OUTPUT:
  74. case Stream_ERROR: {
  75. auto& streamData = this->Stdio[stdio];
  76. streamData.Type = None;
  77. break;
  78. }
  79. }
  80. return *this;
  81. }
  82. cmUVProcessChainBuilder& cmUVProcessChainBuilder::SetBuiltinStream(
  83. Stream stdio)
  84. {
  85. switch (stdio) {
  86. case Stream_INPUT:
  87. // FIXME
  88. break;
  89. case Stream_OUTPUT:
  90. case Stream_ERROR: {
  91. auto& streamData = this->Stdio[stdio];
  92. streamData.Type = Builtin;
  93. break;
  94. }
  95. }
  96. return *this;
  97. }
  98. cmUVProcessChainBuilder& cmUVProcessChainBuilder::SetExternalStream(
  99. Stream stdio, int fd)
  100. {
  101. switch (stdio) {
  102. case Stream_INPUT:
  103. case Stream_OUTPUT:
  104. case Stream_ERROR: {
  105. auto& streamData = this->Stdio[stdio];
  106. streamData.Type = External;
  107. streamData.FileDescriptor = fd;
  108. break;
  109. }
  110. }
  111. return *this;
  112. }
  113. cmUVProcessChainBuilder& cmUVProcessChainBuilder::SetExternalStream(
  114. Stream stdio, FILE* stream)
  115. {
  116. int fd = cm_fileno(stream);
  117. if (fd >= 0) {
  118. return this->SetExternalStream(stdio, fd);
  119. }
  120. return this->SetNoStream(stdio);
  121. }
  122. cmUVProcessChainBuilder& cmUVProcessChainBuilder::SetMergedBuiltinStreams()
  123. {
  124. this->MergedBuiltinStreams = true;
  125. return this->SetBuiltinStream(Stream_OUTPUT).SetBuiltinStream(Stream_ERROR);
  126. }
  127. cmUVProcessChainBuilder& cmUVProcessChainBuilder::SetWorkingDirectory(
  128. std::string dir)
  129. {
  130. this->WorkingDirectory = std::move(dir);
  131. return *this;
  132. }
  133. cmUVProcessChainBuilder& cmUVProcessChainBuilder::SetDetached()
  134. {
  135. this->Detached = true;
  136. return *this;
  137. }
  138. uv_loop_t* cmUVProcessChainBuilder::GetLoop() const
  139. {
  140. return this->Loop;
  141. }
  142. cmUVProcessChain cmUVProcessChainBuilder::Start() const
  143. {
  144. cmUVProcessChain chain;
  145. if (!chain.Data->Prepare(this)) {
  146. return chain;
  147. }
  148. for (std::size_t i = 0; i < this->Processes.size(); i++) {
  149. chain.Data->SpawnProcess(i, this->Processes[i], i == 0,
  150. i == this->Processes.size() - 1);
  151. }
  152. chain.Data->Finish();
  153. return chain;
  154. }
  155. bool cmUVProcessChain::InternalData::Prepare(
  156. cmUVProcessChainBuilder const* builder)
  157. {
  158. this->Builder = builder;
  159. if (this->Builder->Loop) {
  160. this->Loop = this->Builder->Loop;
  161. } else {
  162. this->BuiltinLoop.init();
  163. this->Loop = this->BuiltinLoop;
  164. }
  165. auto const& input =
  166. this->Builder->Stdio[cmUVProcessChainBuilder::Stream_INPUT];
  167. auto& inputData = this->InputStreamData;
  168. switch (input.Type) {
  169. case cmUVProcessChainBuilder::None:
  170. inputData.Stdio.flags = UV_IGNORE;
  171. break;
  172. case cmUVProcessChainBuilder::Builtin: {
  173. // FIXME
  174. break;
  175. }
  176. case cmUVProcessChainBuilder::External:
  177. inputData.Stdio.flags = UV_INHERIT_FD;
  178. inputData.Stdio.data.fd = input.FileDescriptor;
  179. break;
  180. }
  181. auto const& error =
  182. this->Builder->Stdio[cmUVProcessChainBuilder::Stream_ERROR];
  183. auto& errorData = this->ErrorStreamData;
  184. switch (error.Type) {
  185. case cmUVProcessChainBuilder::None:
  186. errorData.Stdio.flags = UV_IGNORE;
  187. break;
  188. case cmUVProcessChainBuilder::Builtin: {
  189. int pipeFd[2];
  190. if (cmGetPipes(pipeFd) < 0) {
  191. return false;
  192. }
  193. errorData.BuiltinStream = pipeFd[0];
  194. errorData.Stdio.flags = UV_INHERIT_FD;
  195. errorData.Stdio.data.fd = pipeFd[1];
  196. if (this->TempErrorPipe.init(*this->Loop, 0) < 0) {
  197. return false;
  198. }
  199. if (uv_pipe_open(this->TempErrorPipe, errorData.Stdio.data.fd) < 0) {
  200. return false;
  201. }
  202. break;
  203. }
  204. case cmUVProcessChainBuilder::External:
  205. errorData.Stdio.flags = UV_INHERIT_FD;
  206. errorData.Stdio.data.fd = error.FileDescriptor;
  207. break;
  208. }
  209. auto const& output =
  210. this->Builder->Stdio[cmUVProcessChainBuilder::Stream_OUTPUT];
  211. auto& outputData = this->OutputStreamData;
  212. switch (output.Type) {
  213. case cmUVProcessChainBuilder::None:
  214. outputData.Stdio.flags = UV_IGNORE;
  215. break;
  216. case cmUVProcessChainBuilder::Builtin:
  217. if (this->Builder->MergedBuiltinStreams) {
  218. outputData.BuiltinStream = errorData.BuiltinStream;
  219. outputData.Stdio.flags = UV_INHERIT_FD;
  220. outputData.Stdio.data.fd = errorData.Stdio.data.fd;
  221. } else {
  222. int pipeFd[2];
  223. if (cmGetPipes(pipeFd) < 0) {
  224. return false;
  225. }
  226. outputData.BuiltinStream = pipeFd[0];
  227. outputData.Stdio.flags = UV_INHERIT_FD;
  228. outputData.Stdio.data.fd = pipeFd[1];
  229. if (this->TempOutputPipe.init(*this->Loop, 0) < 0) {
  230. return false;
  231. }
  232. if (uv_pipe_open(this->TempOutputPipe, outputData.Stdio.data.fd) < 0) {
  233. return false;
  234. }
  235. }
  236. break;
  237. case cmUVProcessChainBuilder::External:
  238. outputData.Stdio.flags = UV_INHERIT_FD;
  239. outputData.Stdio.data.fd = output.FileDescriptor;
  240. break;
  241. }
  242. bool first = true;
  243. for (std::size_t i = 0; i < this->Builder->Processes.size(); i++) {
  244. this->Processes.emplace_back(cm::make_unique<ProcessData>());
  245. auto& process = *this->Processes.back();
  246. process.Data = this;
  247. process.ProcessStatus.Finished = false;
  248. if (!first) {
  249. auto& prevProcess = *this->Processes[i - 1];
  250. int pipeFd[2];
  251. if (cmGetPipes(pipeFd) < 0) {
  252. return false;
  253. }
  254. if (prevProcess.OutputPipe.init(*this->Loop, 0) < 0) {
  255. return false;
  256. }
  257. if (uv_pipe_open(prevProcess.OutputPipe, pipeFd[1]) < 0) {
  258. return false;
  259. }
  260. if (process.InputPipe.init(*this->Loop, 0) < 0) {
  261. return false;
  262. }
  263. if (uv_pipe_open(process.InputPipe, pipeFd[0]) < 0) {
  264. return false;
  265. }
  266. }
  267. first = false;
  268. }
  269. return true;
  270. }
  271. void cmUVProcessChain::InternalData::SpawnProcess(
  272. std::size_t index,
  273. cmUVProcessChainBuilder::ProcessConfiguration const& config, bool first,
  274. bool last)
  275. {
  276. auto& process = *this->Processes[index];
  277. auto options = uv_process_options_t();
  278. // Bounds were checked at add time, first element is guaranteed to exist
  279. options.file = config.Arguments[0].c_str();
  280. std::vector<char const*> arguments;
  281. arguments.reserve(config.Arguments.size());
  282. for (auto const& arg : config.Arguments) {
  283. arguments.push_back(arg.c_str());
  284. }
  285. arguments.push_back(nullptr);
  286. options.args = const_cast<char**>(arguments.data());
  287. options.flags = UV_PROCESS_WINDOWS_HIDE;
  288. if (this->Builder->Detached) {
  289. options.flags |= UV_PROCESS_DETACHED;
  290. }
  291. #if UV_VERSION_MAJOR > 1 || \
  292. (UV_VERSION_MAJOR == 1 && UV_VERSION_MINOR >= 48) || \
  293. !defined(CMAKE_USE_SYSTEM_LIBUV)
  294. options.flags |= UV_PROCESS_WINDOWS_FILE_PATH_EXACT_NAME;
  295. #endif
  296. #if UV_VERSION_MAJOR > 1 || !defined(CMAKE_USE_SYSTEM_LIBUV)
  297. options.flags |= UV_PROCESS_WINDOWS_USE_PARENT_ERROR_MODE;
  298. #endif
  299. if (!this->Builder->WorkingDirectory.empty()) {
  300. options.cwd = this->Builder->WorkingDirectory.c_str();
  301. }
  302. std::array<uv_stdio_container_t, 3> stdio;
  303. if (first) {
  304. stdio[0] = this->InputStreamData.Stdio;
  305. } else {
  306. stdio[0] = uv_stdio_container_t();
  307. stdio[0].flags = UV_INHERIT_STREAM;
  308. stdio[0].data.stream = process.InputPipe;
  309. }
  310. if (last) {
  311. stdio[1] = this->OutputStreamData.Stdio;
  312. } else {
  313. stdio[1] = uv_stdio_container_t();
  314. stdio[1].flags = UV_INHERIT_STREAM;
  315. stdio[1].data.stream = process.OutputPipe;
  316. }
  317. stdio[2] = this->ErrorStreamData.Stdio;
  318. options.stdio = stdio.data();
  319. options.stdio_count = 3;
  320. options.exit_cb = [](uv_process_t* handle, int64_t exitStatus,
  321. int termSignal) {
  322. auto* processData = static_cast<ProcessData*>(handle->data);
  323. processData->ProcessStatus.ExitStatus = exitStatus;
  324. processData->ProcessStatus.TermSignal = termSignal;
  325. processData->Finish();
  326. };
  327. if ((process.ProcessStatus.SpawnResult =
  328. process.Process.spawn(*this->Loop, options, &process)) < 0) {
  329. process.Finish();
  330. }
  331. if (this->Builder->Detached) {
  332. uv_unref((uv_handle_t*)process.Process);
  333. }
  334. process.InputPipe.reset();
  335. process.OutputPipe.reset();
  336. }
  337. void cmUVProcessChain::InternalData::Finish()
  338. {
  339. this->TempOutputPipe.reset();
  340. this->TempErrorPipe.reset();
  341. this->Valid = true;
  342. }
  343. cmUVProcessChain::cmUVProcessChain()
  344. : Data(cm::make_unique<InternalData>())
  345. {
  346. }
  347. cmUVProcessChain::cmUVProcessChain(cmUVProcessChain&& other) noexcept
  348. : Data(std::move(other.Data))
  349. {
  350. }
  351. cmUVProcessChain::~cmUVProcessChain() = default;
  352. cmUVProcessChain& cmUVProcessChain::operator=(
  353. cmUVProcessChain&& other) noexcept
  354. {
  355. this->Data = std::move(other.Data);
  356. return *this;
  357. }
  358. uv_loop_t& cmUVProcessChain::GetLoop()
  359. {
  360. return *this->Data->Loop;
  361. }
  362. int cmUVProcessChain::OutputStream()
  363. {
  364. return this->Data->OutputStreamData.BuiltinStream;
  365. }
  366. int cmUVProcessChain::ErrorStream()
  367. {
  368. return this->Data->ErrorStreamData.BuiltinStream;
  369. }
  370. bool cmUVProcessChain::Valid() const
  371. {
  372. return this->Data->Valid;
  373. }
  374. bool cmUVProcessChain::Wait(uint64_t milliseconds)
  375. {
  376. bool timeout = false;
  377. cm::uv_timer_ptr timer;
  378. if (milliseconds > 0) {
  379. timer.init(*this->Data->Loop, &timeout);
  380. timer.start(
  381. [](uv_timer_t* handle) {
  382. auto* timeoutPtr = static_cast<bool*>(handle->data);
  383. *timeoutPtr = true;
  384. },
  385. milliseconds, 0);
  386. }
  387. while (!timeout &&
  388. this->Data->ProcessesCompleted < this->Data->Processes.size()) {
  389. uv_run(this->Data->Loop, UV_RUN_ONCE);
  390. }
  391. return !timeout;
  392. }
  393. std::vector<cmUVProcessChain::Status const*> cmUVProcessChain::GetStatus()
  394. const
  395. {
  396. std::vector<cmUVProcessChain::Status const*> statuses(
  397. this->Data->Processes.size(), nullptr);
  398. for (std::size_t i = 0; i < statuses.size(); i++) {
  399. statuses[i] = &this->GetStatus(i);
  400. }
  401. return statuses;
  402. }
  403. cmUVProcessChain::Status const& cmUVProcessChain::GetStatus(
  404. std::size_t index) const
  405. {
  406. return this->Data->Processes[index]->ProcessStatus;
  407. }
  408. bool cmUVProcessChain::Finished() const
  409. {
  410. return this->Data->ProcessesCompleted >= this->Data->Processes.size();
  411. }
  412. std::pair<cmUVProcessChain::ExceptionCode, std::string>
  413. cmUVProcessChain::Status::GetException() const
  414. {
  415. if (this->SpawnResult) {
  416. return std::make_pair(ExceptionCode::Spawn,
  417. uv_strerror(this->SpawnResult));
  418. }
  419. #ifdef _WIN32
  420. if (this->Finished && (this->ExitStatus & 0xF0000000) == 0xC0000000) {
  421. // Child terminated due to exceptional behavior.
  422. switch (this->ExitStatus) {
  423. case STATUS_CONTROL_C_EXIT:
  424. return std::make_pair(ExceptionCode::Interrupt, "User interrupt");
  425. case STATUS_FLOAT_DENORMAL_OPERAND:
  426. return std::make_pair(ExceptionCode::Numerical,
  427. "Floating-point exception (denormal operand)");
  428. case STATUS_FLOAT_DIVIDE_BY_ZERO:
  429. return std::make_pair(ExceptionCode::Numerical, "Divide-by-zero");
  430. case STATUS_FLOAT_INEXACT_RESULT:
  431. return std::make_pair(ExceptionCode::Numerical,
  432. "Floating-point exception (inexact result)");
  433. case STATUS_FLOAT_INVALID_OPERATION:
  434. return std::make_pair(ExceptionCode::Numerical,
  435. "Invalid floating-point operation");
  436. case STATUS_FLOAT_OVERFLOW:
  437. return std::make_pair(ExceptionCode::Numerical,
  438. "Floating-point overflow");
  439. case STATUS_FLOAT_STACK_CHECK:
  440. return std::make_pair(ExceptionCode::Numerical,
  441. "Floating-point stack check failed");
  442. case STATUS_FLOAT_UNDERFLOW:
  443. return std::make_pair(ExceptionCode::Numerical,
  444. "Floating-point underflow");
  445. # ifdef STATUS_FLOAT_MULTIPLE_FAULTS
  446. case STATUS_FLOAT_MULTIPLE_FAULTS:
  447. return std::make_pair(ExceptionCode::Numerical,
  448. "Floating-point exception (multiple faults)");
  449. # endif
  450. # ifdef STATUS_FLOAT_MULTIPLE_TRAPS
  451. case STATUS_FLOAT_MULTIPLE_TRAPS:
  452. return std::make_pair(ExceptionCode::Numerical,
  453. "Floating-point exception (multiple traps)");
  454. # endif
  455. case STATUS_INTEGER_DIVIDE_BY_ZERO:
  456. return std::make_pair(ExceptionCode::Numerical,
  457. "Integer divide-by-zero");
  458. case STATUS_INTEGER_OVERFLOW:
  459. return std::make_pair(ExceptionCode::Numerical, "Integer overflow");
  460. case STATUS_DATATYPE_MISALIGNMENT:
  461. return std::make_pair(ExceptionCode::Fault, "Datatype misalignment");
  462. case STATUS_ACCESS_VIOLATION:
  463. return std::make_pair(ExceptionCode::Fault, "Access violation");
  464. case STATUS_IN_PAGE_ERROR:
  465. return std::make_pair(ExceptionCode::Fault, "In-page error");
  466. case STATUS_INVALID_HANDLE:
  467. return std::make_pair(ExceptionCode::Fault, "Invalid handle");
  468. case STATUS_NONCONTINUABLE_EXCEPTION:
  469. return std::make_pair(ExceptionCode::Fault,
  470. "Noncontinuable exception");
  471. case STATUS_INVALID_DISPOSITION:
  472. return std::make_pair(ExceptionCode::Fault, "Invalid disposition");
  473. case STATUS_ARRAY_BOUNDS_EXCEEDED:
  474. return std::make_pair(ExceptionCode::Fault, "Array bounds exceeded");
  475. case STATUS_STACK_OVERFLOW:
  476. return std::make_pair(ExceptionCode::Fault, "Stack overflow");
  477. case STATUS_ILLEGAL_INSTRUCTION:
  478. return std::make_pair(ExceptionCode::Illegal, "Illegal instruction");
  479. case STATUS_PRIVILEGED_INSTRUCTION:
  480. return std::make_pair(ExceptionCode::Illegal,
  481. "Privileged instruction");
  482. case STATUS_NO_MEMORY:
  483. default: {
  484. char buf[256];
  485. snprintf(buf, sizeof(buf), "Exit code 0x%x\n",
  486. static_cast<unsigned int>(this->ExitStatus));
  487. return std::make_pair(ExceptionCode::Other, buf);
  488. }
  489. }
  490. }
  491. #else
  492. if (this->Finished && this->TermSignal) {
  493. switch (this->TermSignal) {
  494. # ifdef SIGSEGV
  495. case SIGSEGV:
  496. return std::make_pair(ExceptionCode::Fault, "Segmentation fault");
  497. # endif
  498. # ifdef SIGBUS
  499. # if !defined(SIGSEGV) || SIGBUS != SIGSEGV
  500. case SIGBUS:
  501. return std::make_pair(ExceptionCode::Fault, "Bus error");
  502. # endif
  503. # endif
  504. # ifdef SIGFPE
  505. case SIGFPE:
  506. return std::make_pair(ExceptionCode::Numerical,
  507. "Floating-point exception");
  508. # endif
  509. # ifdef SIGILL
  510. case SIGILL:
  511. return std::make_pair(ExceptionCode::Illegal, "Illegal instruction");
  512. # endif
  513. # ifdef SIGINT
  514. case SIGINT:
  515. return std::make_pair(ExceptionCode::Interrupt, "User interrupt");
  516. # endif
  517. # ifdef SIGABRT
  518. case SIGABRT:
  519. return std::make_pair(ExceptionCode::Other, "Subprocess aborted");
  520. # endif
  521. # ifdef SIGKILL
  522. case SIGKILL:
  523. return std::make_pair(ExceptionCode::Other, "Subprocess killed");
  524. # endif
  525. # ifdef SIGTERM
  526. case SIGTERM:
  527. return std::make_pair(ExceptionCode::Other, "Subprocess terminated");
  528. # endif
  529. # ifdef SIGHUP
  530. case SIGHUP:
  531. return std::make_pair(ExceptionCode::Other, "SIGHUP");
  532. # endif
  533. # ifdef SIGQUIT
  534. case SIGQUIT:
  535. return std::make_pair(ExceptionCode::Other, "SIGQUIT");
  536. # endif
  537. # ifdef SIGTRAP
  538. case SIGTRAP:
  539. return std::make_pair(ExceptionCode::Other, "SIGTRAP");
  540. # endif
  541. # ifdef SIGIOT
  542. # if !defined(SIGABRT) || SIGIOT != SIGABRT
  543. case SIGIOT:
  544. return std::make_pair(ExceptionCode::Other, "SIGIOT");
  545. # endif
  546. # endif
  547. # ifdef SIGUSR1
  548. case SIGUSR1:
  549. return std::make_pair(ExceptionCode::Other, "SIGUSR1");
  550. # endif
  551. # ifdef SIGUSR2
  552. case SIGUSR2:
  553. return std::make_pair(ExceptionCode::Other, "SIGUSR2");
  554. # endif
  555. # ifdef SIGPIPE
  556. case SIGPIPE:
  557. return std::make_pair(ExceptionCode::Other, "SIGPIPE");
  558. # endif
  559. # ifdef SIGALRM
  560. case SIGALRM:
  561. return std::make_pair(ExceptionCode::Other, "SIGALRM");
  562. # endif
  563. # ifdef SIGSTKFLT
  564. case SIGSTKFLT:
  565. return std::make_pair(ExceptionCode::Other, "SIGSTKFLT");
  566. # endif
  567. # ifdef SIGCHLD
  568. case SIGCHLD:
  569. return std::make_pair(ExceptionCode::Other, "SIGCHLD");
  570. # elif defined(SIGCLD)
  571. case SIGCLD:
  572. return std::make_pair(ExceptionCode::Other, "SIGCLD");
  573. # endif
  574. # ifdef SIGCONT
  575. case SIGCONT:
  576. return std::make_pair(ExceptionCode::Other, "SIGCONT");
  577. # endif
  578. # ifdef SIGSTOP
  579. case SIGSTOP:
  580. return std::make_pair(ExceptionCode::Other, "SIGSTOP");
  581. # endif
  582. # ifdef SIGTSTP
  583. case SIGTSTP:
  584. return std::make_pair(ExceptionCode::Other, "SIGTSTP");
  585. # endif
  586. # ifdef SIGTTIN
  587. case SIGTTIN:
  588. return std::make_pair(ExceptionCode::Other, "SIGTTIN");
  589. # endif
  590. # ifdef SIGTTOU
  591. case SIGTTOU:
  592. return std::make_pair(ExceptionCode::Other, "SIGTTOU");
  593. # endif
  594. # ifdef SIGURG
  595. case SIGURG:
  596. return std::make_pair(ExceptionCode::Other, "SIGURG");
  597. # endif
  598. # ifdef SIGXCPU
  599. case SIGXCPU:
  600. return std::make_pair(ExceptionCode::Other, "SIGXCPU");
  601. # endif
  602. # ifdef SIGXFSZ
  603. case SIGXFSZ:
  604. return std::make_pair(ExceptionCode::Other, "SIGXFSZ");
  605. # endif
  606. # ifdef SIGVTALRM
  607. case SIGVTALRM:
  608. return std::make_pair(ExceptionCode::Other, "SIGVTALRM");
  609. # endif
  610. # ifdef SIGPROF
  611. case SIGPROF:
  612. return std::make_pair(ExceptionCode::Other, "SIGPROF");
  613. # endif
  614. # ifdef SIGWINCH
  615. case SIGWINCH:
  616. return std::make_pair(ExceptionCode::Other, "SIGWINCH");
  617. # endif
  618. # ifdef SIGPOLL
  619. case SIGPOLL:
  620. return std::make_pair(ExceptionCode::Other, "SIGPOLL");
  621. # endif
  622. # ifdef SIGIO
  623. # if !defined(SIGPOLL) || SIGIO != SIGPOLL
  624. case SIGIO:
  625. return std::make_pair(ExceptionCode::Other, "SIGIO");
  626. # endif
  627. # endif
  628. # ifdef SIGPWR
  629. case SIGPWR:
  630. return std::make_pair(ExceptionCode::Other, "SIGPWR");
  631. # endif
  632. # ifdef SIGSYS
  633. case SIGSYS:
  634. return std::make_pair(ExceptionCode::Other, "SIGSYS");
  635. # endif
  636. # ifdef SIGUNUSED
  637. # if !defined(SIGSYS) || SIGUNUSED != SIGSYS
  638. case SIGUNUSED:
  639. return std::make_pair(ExceptionCode::Other, "SIGUNUSED");
  640. # endif
  641. # endif
  642. default: {
  643. char buf[256];
  644. snprintf(buf, sizeof(buf), "Signal %d", this->TermSignal);
  645. return std::make_pair(ExceptionCode::Other, buf);
  646. }
  647. }
  648. }
  649. #endif
  650. return std::make_pair(ExceptionCode::None, "");
  651. }
  652. void cmUVProcessChain::InternalData::ProcessData::Finish()
  653. {
  654. this->ProcessStatus.Finished = true;
  655. this->Data->ProcessesCompleted++;
  656. }