cmUVProcessChain.cxx 20 KB

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