cmUVProcessChain.cxx 20 KB

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