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