Coverage Report

Created: 2026-04-29 07:01

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