Coverage Report

Created: 2026-02-09 06:05

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