cmUVProcessChain.cxx 19 KB

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