Coverage Report

Created: 2026-09-01 13:33

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/root/bitcoin/src/util/subprocess.h
Line
Count
Source
1
// Based on the https://github.com/arun11299/cpp-subprocess project.
2
3
/*!
4
5
Documentation for C++ subprocessing library.
6
7
@copyright The code is licensed under the [MIT
8
  License](http://opensource.org/licenses/MIT):
9
  <br>
10
  Copyright &copy; 2016-2018 Arun Muralidharan.
11
  <br>
12
  Permission is hereby granted, free of charge, to any person obtaining a copy
13
  of this software and associated documentation files (the "Software"), to deal
14
  in the Software without restriction, including without limitation the rights
15
  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16
  copies of the Software, and to permit persons to whom the Software is
17
  furnished to do so, subject to the following conditions:
18
  <br>
19
  The above copyright notice and this permission notice shall be included in
20
  all copies or substantial portions of the Software.
21
  <br>
22
  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23
  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24
  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28
  SOFTWARE.
29
30
@author [Arun Muralidharan]
31
@see https://github.com/arun11299/cpp-subprocess to download the source code
32
33
@version 1.0.0
34
*/
35
36
#ifndef BITCOIN_UTIL_SUBPROCESS_H
37
#define BITCOIN_UTIL_SUBPROCESS_H
38
39
#include <util/check.h>
40
#include <util/syserror.h>
41
42
#include <algorithm>
43
#include <csignal>
44
#include <cstdio>
45
#include <cstdlib>
46
#include <cstring>
47
#include <exception>
48
#include <future>
49
#include <initializer_list>
50
#include <iostream>
51
#include <map>
52
#include <memory>
53
#include <sstream>
54
#include <string>
55
#include <vector>
56
57
extern "C" {
58
#ifdef WIN32
59
  #include <windows.h>
60
  #include <io.h>
61
#else
62
  #include <sys/wait.h>
63
  #include <unistd.h>
64
#endif
65
  #include <csignal>
66
  #include <fcntl.h>
67
  #include <sys/types.h>
68
}
69
70
// The Microsoft C++ compiler issues deprecation warnings
71
// for the standard POSIX function names.
72
// Its preferred implementations have a leading underscore.
73
// See: https://learn.microsoft.com/en-us/cpp/c-runtime-library/compatibility.
74
#if (defined _MSC_VER)
75
  #define subprocess_close _close
76
  #define subprocess_fileno _fileno
77
  #define subprocess_open _open
78
  #define subprocess_write _write
79
#else
80
0
  #define subprocess_close close
81
0
  #define subprocess_fileno fileno
82
  #define subprocess_open open
83
0
  #define subprocess_write write
84
#endif
85
86
/*!
87
 * Getting started with reading this source code.
88
 * The source is mainly divided into four parts:
89
 * 1. Exception Classes:
90
 *    These are very basic exception classes derived from
91
 *    runtime_error exception.
92
 *    There are two types of exception thrown from subprocess
93
 *    library: OSError and CalledProcessError
94
 *
95
 * 2. Popen Class
96
 *    This is the main class the users will deal with. It
97
 *    provides with all the API's to deal with processes.
98
 *
99
 * 3. Util namespace
100
 *    It includes some helper functions to split/join a string,
101
 *    reading from file descriptors, waiting on a process, fcntl
102
 *    options on file descriptors etc.
103
 *
104
 * 4. Detail namespace
105
 *    This includes some metaprogramming and helper classes.
106
 */
107
108
109
namespace subprocess {
110
111
// Max buffer size allocated on stack for read error
112
// from pipe
113
inline constexpr size_t SP_MAX_ERR_BUF_SIZ = 1024;
114
115
// Default buffer capacity for OutBuffer and ErrBuffer.
116
// If the data exceeds this capacity, the buffer size is grown
117
// by 1.5 times its previous capacity
118
inline constexpr size_t DEFAULT_BUF_CAP_BYTES = 8192;
119
120
121
/*-----------------------------------------------
122
 *    EXCEPTION CLASSES
123
 *-----------------------------------------------
124
 */
125
126
/*!
127
 * class: CalledProcessError
128
 * Thrown when there was error executing the command.
129
 * Check Popen class API's to know when this exception
130
 * can be thrown.
131
 *
132
 */
133
class CalledProcessError: public std::runtime_error
134
{
135
public:
136
  int retcode;
137
  CalledProcessError(const std::string& error_msg, int retcode):
138
0
    std::runtime_error(error_msg), retcode(retcode)
139
0
  {}
140
};
141
142
143
/*!
144
 * class: OSError
145
 * Thrown when some system call fails to execute or give result.
146
 * The exception message contains the name of the failed system call
147
 * with the stringisized errno code.
148
 * Check Popen class API's to know when this exception would be
149
 * thrown.
150
 * Its usual that the API exception specification would have
151
 * this exception together with CalledProcessError.
152
 */
153
class OSError: public std::runtime_error
154
{
155
public:
156
  OSError(const std::string& err_msg, int err_code):
157
0
    std::runtime_error(err_msg + ": " + SysErrorString(err_code))
158
0
  {}
159
};
160
161
//--------------------------------------------------------------------
162
namespace util
163
{
164
#ifdef WIN32
165
  inline void quote_argument(const std::string &argument, std::string &command_line,
166
                      bool force)
167
  {
168
    constexpr char quote = '"';
169
    constexpr char backslash = '\\';
170
171
    //
172
    // Unless we're told otherwise, don't quote unless we actually
173
    // need to do so --- hopefully avoid problems if programs won't
174
    // parse quotes properly
175
    //
176
177
    if (force == false && argument.empty() == false &&
178
        argument.find_first_of(" \t\n\v") == argument.npos) {
179
      command_line.append(argument);
180
    }
181
    else {
182
      command_line.push_back(quote);
183
184
      for (auto it = argument.begin();; ++it) {
185
        unsigned number_backslashes = 0;
186
187
        while (it != argument.end() && *it == backslash) {
188
          ++it;
189
          ++number_backslashes;
190
        }
191
192
        if (it == argument.end()) {
193
194
          //
195
          // Escape all backslashes, but let the terminating
196
          // double quotation mark we add below be interpreted
197
          // as a metacharacter.
198
          //
199
200
          command_line.append(number_backslashes * 2, backslash);
201
          break;
202
        }
203
        else if (*it == quote) {
204
205
          //
206
          // Escape all backslashes and the following
207
          // double quotation mark.
208
          //
209
210
          command_line.append(number_backslashes * 2 + 1, backslash);
211
          command_line.push_back(*it);
212
        }
213
        else {
214
215
          //
216
          // Backslashes aren't special here.
217
          //
218
219
          command_line.append(number_backslashes, backslash);
220
          command_line.push_back(*it);
221
        }
222
      }
223
224
      command_line.push_back(quote);
225
    }
226
  }
227
228
  inline std::string get_last_error(DWORD errorMessageID)
229
  {
230
    if (errorMessageID == 0)
231
      return std::string();
232
233
    LPSTR messageBuffer = nullptr;
234
    size_t size = FormatMessageA(
235
        FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
236
            FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_MAX_WIDTH_MASK,
237
        NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
238
        (LPSTR)&messageBuffer, 0, NULL);
239
240
    std::string message(messageBuffer, size);
241
242
    LocalFree(messageBuffer);
243
244
    return message;
245
  }
246
247
  inline FILE *file_from_handle(HANDLE h, const char *mode)
248
  {
249
    int md;
250
    if (!mode) {
251
      throw OSError("invalid_mode", 0);
252
    }
253
254
    if (mode[0] == 'w') {
255
      md = _O_WRONLY;
256
    }
257
    else if (mode[0] == 'r') {
258
      md = _O_RDONLY;
259
    }
260
    else {
261
      throw OSError("file_from_handle", 0);
262
    }
263
264
    int os_fhandle = _open_osfhandle((intptr_t)h, md);
265
    if (os_fhandle == -1) {
266
      CloseHandle(h);
267
      throw OSError("_open_osfhandle", 0);
268
    }
269
270
    FILE *fp = _fdopen(os_fhandle, mode);
271
    if (fp == 0) {
272
      subprocess_close(os_fhandle);
273
      throw OSError("_fdopen", 0);
274
    }
275
276
    return fp;
277
  }
278
279
  inline void configure_pipe(HANDLE* read_handle, HANDLE* write_handle, HANDLE* child_handle)
280
  {
281
    SECURITY_ATTRIBUTES saAttr;
282
283
    // Set the bInheritHandle flag so pipe handles are inherited.
284
    saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
285
    saAttr.bInheritHandle = TRUE;
286
    saAttr.lpSecurityDescriptor = NULL;
287
288
    // Create a pipe for the child process's STDIN.
289
    if (!CreatePipe(read_handle, write_handle, &saAttr,0))
290
      throw OSError("CreatePipe", 0);
291
292
    // Ensure the write handle to the pipe for STDIN is not inherited.
293
    if (!SetHandleInformation(*child_handle, HANDLE_FLAG_INHERIT, 0))
294
      throw OSError("SetHandleInformation", 0);
295
  }
296
#endif
297
298
  /*!
299
   * Function: split
300
   * Parameters:
301
   * [in] str : Input string which needs to be split based upon the
302
   *            delimiters provided.
303
   * [in] deleims : Delimiter characters based upon which the string needs
304
   *                to be split. Default constructed to ' '(space) and '\t'(tab)
305
   * [out] vector<string> : Vector of strings split at deleimiter.
306
   */
307
  static inline std::vector<std::string>
308
  split(const std::string& str, const std::string& delims=" \t")
309
0
  {
310
0
    std::vector<std::string> res;
311
0
    size_t init = 0;
312
313
0
    while (true) {
  Branch (313:12): [Folded - Ignored]
314
0
      auto pos = str.find_first_of(delims, init);
315
0
      if (pos == std::string::npos) {
  Branch (315:11): [True: 0, False: 0]
316
0
        res.emplace_back(str.substr(init, str.length()));
317
0
        break;
318
0
      }
319
0
      res.emplace_back(str.substr(init, pos - init));
320
0
      pos++;
321
0
      init = pos;
322
0
    }
323
324
0
    return res;
325
0
  }
Unexecuted instantiation: external_signer.cpp:_ZN10subprocess4utilL5splitERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES8_
Unexecuted instantiation: run_command.cpp:_ZN10subprocess4utilL5splitERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES8_
326
327
328
#ifndef WIN32
329
  /*!
330
   * Function: set_clo_on_exec
331
   * Sets/Resets the FD_CLOEXEC flag on the provided file descriptor
332
   * based upon the `set` parameter.
333
   * Parameters:
334
   * [in] fd : The descriptor on which FD_CLOEXEC needs to be set/reset.
335
   * [in] set : If 'true', set FD_CLOEXEC.
336
   *            If 'false' unset FD_CLOEXEC.
337
   */
338
  static inline
339
  void set_clo_on_exec(int fd, bool set = true)
340
0
  {
341
0
    int flags = fcntl(fd, F_GETFD, 0);
342
0
    if (flags == -1) {
  Branch (342:9): [True: 0, False: 0]
343
0
        throw OSError("fcntl F_GETFD failed", errno);
344
0
    }
345
0
    if (set) flags |= FD_CLOEXEC;
  Branch (345:9): [True: 0, False: 0]
346
0
    else flags &= ~FD_CLOEXEC;
347
0
    if (fcntl(fd, F_SETFD, flags) == -1) {
  Branch (347:9): [True: 0, False: 0]
348
0
        throw OSError("fcntl F_SETFD failed", errno);
349
0
    }
350
0
  }
Unexecuted instantiation: external_signer.cpp:_ZN10subprocess4utilL15set_clo_on_execEib
Unexecuted instantiation: run_command.cpp:_ZN10subprocess4utilL15set_clo_on_execEib
351
352
353
  /*!
354
   * Function: pipe_cloexec
355
   * Creates a pipe and sets FD_CLOEXEC flag on both
356
   * read and write descriptors of the pipe.
357
   * Parameters:
358
   * [out] : A pair of file descriptors.
359
   *         First element of pair is the read descriptor of pipe.
360
   *         Second element is the write descriptor of pipe.
361
   */
362
  static inline
363
  std::pair<int, int> pipe_cloexec() noexcept(false)
364
0
  {
365
0
    int pipe_fds[2];
366
0
    int res = pipe(pipe_fds);
367
0
    if (res) {
  Branch (367:9): [True: 0, False: 0]
368
0
      throw OSError("pipe failure", errno);
369
0
    }
370
371
0
    set_clo_on_exec(pipe_fds[0]);
372
0
    set_clo_on_exec(pipe_fds[1]);
373
374
0
    return std::make_pair(pipe_fds[0], pipe_fds[1]);
375
0
  }
Unexecuted instantiation: external_signer.cpp:_ZN10subprocess4utilL12pipe_cloexecEv
Unexecuted instantiation: run_command.cpp:_ZN10subprocess4utilL12pipe_cloexecEv
376
#endif
377
378
379
  /*!
380
   * Function: write_n
381
   * Writes `length` bytes to the file descriptor `fd`
382
   * from the buffer `buf`.
383
   * Parameters:
384
   * [in] fd : The file descriptotr to write to.
385
   * [in] buf: Buffer from which data needs to be written to fd.
386
   * [in] length: The number of bytes that needs to be written from
387
   *              `buf` to `fd`.
388
   * [out] int : Number of bytes written or -1 in case of failure.
389
   */
390
  static inline
391
  int write_n(int fd, const char* buf, size_t length)
392
0
  {
393
0
    size_t nwritten = 0;
394
0
    while (nwritten < length) {
  Branch (394:12): [True: 0, False: 0]
395
0
      int written = subprocess_write(fd, buf + nwritten, length - nwritten);
396
0
      if (written == -1) return -1;
  Branch (396:11): [True: 0, False: 0]
397
0
      nwritten += written;
398
0
    }
399
0
    return nwritten;
400
0
  }
Unexecuted instantiation: external_signer.cpp:_ZN10subprocess4utilL7write_nEiPKcm
Unexecuted instantiation: run_command.cpp:_ZN10subprocess4utilL7write_nEiPKcm
401
402
403
  /*!
404
   * Function: read_atmost_n
405
   * Reads at the most `read_upto` bytes from the
406
   * file object `fp` before returning.
407
   * Parameters:
408
   * [in] fp : The file object from which it needs to read.
409
   * [in] buf : The buffer into which it needs to write the data.
410
   * [in] read_upto: Max number of bytes which must be read from `fd`.
411
   * [out] int : Number of bytes written to `buf` or read from `fd`
412
   *             OR -1 in case of error.
413
   *  NOTE: In case of EINTR while reading from socket, this API
414
   *  will retry to read from `fd`, but only till the EINTR counter
415
   *  reaches 50 after which it will return with whatever data it read.
416
   */
417
  static inline
418
  int read_atmost_n(FILE* fp, char* buf, size_t read_upto)
419
0
  {
420
#ifdef WIN32
421
    return (int)fread(buf, 1, read_upto, fp);
422
#else
423
0
    int fd = subprocess_fileno(fp);
424
0
    int rbytes = 0;
425
0
    int eintr_cnter = 0;
426
427
0
    while (1) {
  Branch (427:12): [Folded - Ignored]
428
0
      int read_bytes = read(fd, buf + rbytes, read_upto - rbytes);
429
0
      if (read_bytes == -1) {
  Branch (429:11): [True: 0, False: 0]
430
0
        if (errno == EINTR) {
  Branch (430:13): [True: 0, False: 0]
431
0
          if (eintr_cnter >= 50) return -1;
  Branch (431:15): [True: 0, False: 0]
432
0
          eintr_cnter++;
433
0
          continue;
434
0
        }
435
0
        return -1;
436
0
      }
437
0
      if (read_bytes == 0) return rbytes;
  Branch (437:11): [True: 0, False: 0]
438
439
0
      rbytes += read_bytes;
440
0
    }
441
0
    return rbytes;
442
0
#endif
443
0
  }
Unexecuted instantiation: external_signer.cpp:_ZN10subprocess4utilL13read_atmost_nEP8_IO_FILEPcm
Unexecuted instantiation: run_command.cpp:_ZN10subprocess4utilL13read_atmost_nEP8_IO_FILEPcm
444
445
446
  /*!
447
   * Function: read_all
448
   * Reads all the available data from `fp` into
449
   * `buf`. Internally calls read_atmost_n.
450
   * Parameters:
451
   * [in] fp : The file object from which to read from.
452
   * [in] buf : The buffer of type `class Buffer` into which
453
   *            the read data is written to.
454
   * [out] int: Number of bytes read OR -1 in case of failure.
455
   *
456
   * NOTE: `class Buffer` is a exposed public class. See below.
457
   */
458
459
  static inline int read_all(FILE* fp, std::vector<char>& buf)
460
0
  {
461
0
    auto buffer = buf.data();
462
0
    int total_bytes_read = 0;
463
0
    int fill_sz = buf.size();
464
465
0
    while (1) {
  Branch (465:12): [Folded - Ignored]
466
0
      const int rd_bytes = read_atmost_n(fp, buffer, fill_sz);
467
468
0
      if (rd_bytes == -1) { // Read finished
  Branch (468:11): [True: 0, False: 0]
469
0
        if (total_bytes_read == 0) return -1;
  Branch (469:13): [True: 0, False: 0]
470
0
        break;
471
472
0
      } else if (rd_bytes == fill_sz) { // Buffer full
  Branch (472:18): [True: 0, False: 0]
473
0
        const auto orig_sz = buf.size();
474
0
        const auto new_sz = orig_sz * 2;
475
0
        buf.resize(new_sz);
476
0
        fill_sz = new_sz - orig_sz;
477
478
        //update the buffer pointer
479
0
        buffer = buf.data();
480
0
        total_bytes_read += rd_bytes;
481
0
        buffer += total_bytes_read;
482
483
0
      } else { // Partial data ? Continue reading
484
0
        total_bytes_read += rd_bytes;
485
0
        fill_sz -= rd_bytes;
486
0
        break;
487
0
      }
488
0
    }
489
0
    buf.erase(buf.begin()+total_bytes_read, buf.end()); // remove extra nulls
490
0
    return total_bytes_read;
491
0
  }
Unexecuted instantiation: external_signer.cpp:_ZN10subprocess4utilL8read_allEP8_IO_FILERSt6vectorIcSaIcEE
Unexecuted instantiation: run_command.cpp:_ZN10subprocess4utilL8read_allEP8_IO_FILERSt6vectorIcSaIcEE
492
493
#ifndef WIN32
494
  /*!
495
   * Function: wait_for_child_exit
496
   * Waits for the process with pid `pid` to exit
497
   * and returns its status.
498
   * Parameters:
499
   * [in] pid : The pid of the process.
500
   * [out] pair<int, int>:
501
   *    pair.first : Return code of the waitpid call.
502
   *    pair.second : Exit status of the process.
503
   *
504
   *  NOTE: This is a blocking call as in, it will loop
505
   *  till the child is exited.
506
   */
507
  static inline
508
  std::pair<int, int> wait_for_child_exit(int pid)
509
0
  {
510
0
    int status = 0;
511
0
    int ret = -1;
512
0
    while (1) {
  Branch (512:12): [Folded - Ignored]
513
0
      ret = waitpid(pid, &status, 0);
514
0
      if (ret == -1) break;
  Branch (514:11): [True: 0, False: 0]
515
0
      if (ret == 0) continue;
  Branch (515:11): [True: 0, False: 0]
516
0
      return std::make_pair(ret, status);
517
0
    }
518
519
0
    return std::make_pair(ret, status);
520
0
  }
Unexecuted instantiation: external_signer.cpp:_ZN10subprocess4utilL19wait_for_child_exitEi
Unexecuted instantiation: run_command.cpp:_ZN10subprocess4utilL19wait_for_child_exitEi
521
#endif
522
523
} // end namespace util
524
525
526
527
/* -------------------------------
528
 *     Popen Arguments
529
 * -------------------------------
530
 */
531
532
/*!
533
 * Base class for all arguments involving string value.
534
 */
535
struct string_arg
536
{
537
0
  string_arg(const char* arg): arg_value(arg) {}
538
0
  string_arg(std::string&& arg): arg_value(std::move(arg)) {}
539
0
  string_arg(const std::string& arg): arg_value(arg) {}
540
  std::string arg_value;
541
};
542
543
/*!
544
 * Option to specify the executable name separately
545
 * from the args sequence.
546
 * In this case the cmd args must only contain the
547
 * options required for this executable.
548
 *
549
 * Eg: executable{"ls"}
550
 */
551
struct executable: string_arg
552
{
553
  template <typename T>
554
  executable(T&& arg): string_arg(std::forward<T>(arg)) {}
555
};
556
557
/*!
558
 * Used for redirecting input/output/error
559
 */
560
enum IOTYPE {
561
  STDOUT = 1,
562
  STDERR,
563
  PIPE,
564
};
565
566
//TODO: A common base/interface for below stream structures ??
567
568
/*!
569
 * Option to specify the input channel for the child
570
 * process. It can be:
571
 * 1. An already open file descriptor.
572
 * 2. A file name.
573
 * 3. IOTYPE. Usual a PIPE
574
 *
575
 * Eg: input{PIPE}
576
 * OR in case of redirection, output of another Popen
577
 * input{popen.output()}
578
 */
579
struct input
580
{
581
  // For an already existing file descriptor.
582
0
  explicit input(int fd): rd_ch_(fd) {}
583
584
  // FILE pointer.
585
0
  explicit input (FILE* fp):input(subprocess_fileno(fp)) { assert(fp); }
586
587
0
  explicit input(const char* filename) {
588
0
    int fd = subprocess_open(filename, O_RDONLY);
589
0
    if (fd == -1) throw OSError("File not found: ", errno);
590
0
    rd_ch_ = fd;
591
0
  }
592
0
  explicit input(IOTYPE typ) {
593
0
    assert (typ == PIPE && "STDOUT/STDERR not allowed");
  Branch (593:5): [True: 0, False: 0]
  Branch (593:5): [Folded - Ignored]
  Branch (593:5): [True: 0, False: 0]
594
0
#ifndef WIN32
595
0
    std::tie(rd_ch_, wr_ch_) = util::pipe_cloexec();
596
0
#endif
597
0
  }
598
599
  int rd_ch_ = -1;
600
  int wr_ch_ = -1;
601
};
602
603
604
/*!
605
 * Option to specify the output channel for the child
606
 * process. It can be:
607
 * 1. An already open file descriptor.
608
 * 2. A file name.
609
 * 3. IOTYPE. Usually a PIPE.
610
 *
611
 * Eg: output{PIPE}
612
 * OR output{"output.txt"}
613
 */
614
struct output
615
{
616
0
  explicit output(int fd): wr_ch_(fd) {}
617
618
0
  explicit output (FILE* fp):output(subprocess_fileno(fp)) { assert(fp); }
619
620
0
  explicit output(const char* filename) {
621
0
    int fd = subprocess_open(filename, O_APPEND | O_CREAT | O_RDWR, 0640);
622
0
    if (fd == -1) throw OSError("File not found: ", errno);
623
0
    wr_ch_ = fd;
624
0
  }
625
0
  explicit output(IOTYPE typ) {
626
0
    assert (typ == PIPE && "STDOUT/STDERR not allowed");
  Branch (626:5): [True: 0, False: 0]
  Branch (626:5): [Folded - Ignored]
  Branch (626:5): [True: 0, False: 0]
627
0
#ifndef WIN32
628
0
    std::tie(rd_ch_, wr_ch_) = util::pipe_cloexec();
629
0
#endif
630
0
  }
631
632
  int rd_ch_ = -1;
633
  int wr_ch_ = -1;
634
};
635
636
637
/*!
638
 * Option to specify the error channel for the child
639
 * process. It can be:
640
 * 1. An already open file descriptor.
641
 * 2. A file name.
642
 * 3. IOTYPE. Usually a PIPE or STDOUT
643
 *
644
 */
645
struct error
646
{
647
0
  explicit error(int fd): wr_ch_(fd) {}
648
649
0
  explicit error(FILE* fp):error(subprocess_fileno(fp)) { assert(fp); }
650
651
0
  explicit error(const char* filename) {
652
0
    int fd = subprocess_open(filename, O_APPEND | O_CREAT | O_RDWR, 0640);
653
0
    if (fd == -1) throw OSError("File not found: ", errno);
654
0
    wr_ch_ = fd;
655
0
  }
656
0
  explicit error(IOTYPE typ) {
657
0
    assert ((typ == PIPE || typ == STDOUT) && "STDERR not allowed");
  Branch (657:5): [True: 0, False: 0]
  Branch (657:5): [True: 0, False: 0]
  Branch (657:5): [Folded - Ignored]
  Branch (657:5): [True: 0, False: 0]
658
0
    if (typ == PIPE) {
  Branch (658:9): [True: 0, False: 0]
659
0
#ifndef WIN32
660
0
      std::tie(rd_ch_, wr_ch_) = util::pipe_cloexec();
661
0
#endif
662
0
    } else {
663
      // Need to defer it till we have checked all arguments
664
0
      deferred_ = true;
665
0
    }
666
0
  }
667
668
  bool deferred_ = false;
669
  int rd_ch_ = -1;
670
  int wr_ch_ = -1;
671
};
672
673
// ~~~~ End Popen Args ~~~~
674
675
676
/*!
677
 * class: Buffer
678
 * This class is a very thin wrapper around std::vector<char>
679
 * This is basically used to determine the length of the actual
680
 * data stored inside the dynamically resized vector.
681
 *
682
 * This is what is returned as the output to the communicate
683
 * function, so, users must know about this class.
684
 *
685
 * OutBuffer and ErrBuffer are just different typedefs to this class.
686
 */
687
class Buffer
688
{
689
public:
690
0
  Buffer() = default;
691
0
  explicit Buffer(size_t cap) { buf.resize(cap); }
692
0
  void add_cap(size_t cap) { buf.resize(cap); }
693
694
public:
695
  std::vector<char> buf;
696
  size_t length = 0;
697
};
698
699
// Buffer for storing output written to output fd
700
using OutBuffer = Buffer;
701
// Buffer for storing output written to error fd
702
using ErrBuffer = Buffer;
703
704
705
// Fwd Decl.
706
class Popen;
707
708
/*---------------------------------------------------
709
 *      DETAIL NAMESPACE
710
 *---------------------------------------------------
711
 */
712
713
namespace detail {
714
/*!
715
 * A helper class to Popen class for setting
716
 * options as provided in the Popen constructor.
717
 * This design allows us to _not_ have any fixed position
718
 * to any arguments and specify them in a way similar to what
719
 * can be done in python.
720
 */
721
struct ArgumentDeducer
722
{
723
0
  ArgumentDeducer(Popen* p): popen_(p) {}
724
725
  void set_option(executable&& exe);
726
  void set_option(input&& inp);
727
  void set_option(output&& out);
728
  void set_option(error&& err);
729
730
private:
731
  Popen* popen_ = nullptr;
732
};
733
734
#ifndef WIN32
735
/*!
736
 * A helper class to Popen.
737
 * This takes care of all the fork-exec logic
738
 * in the execute_child API.
739
 */
740
class Child
741
{
742
public:
743
  Child(Popen* p, int err_wr_pipe):
744
0
    parent_(p),
745
0
    err_wr_pipe_(err_wr_pipe)
746
0
  {}
747
748
  void execute_child();
749
750
private:
751
  // Lets call it parent even though
752
  // technically a bit incorrect
753
  Popen* parent_ = nullptr;
754
  int err_wr_pipe_ = -1;
755
};
756
#endif
757
758
// Fwd Decl.
759
class Streams;
760
761
/*!
762
 * A helper class to Streams.
763
 * This takes care of management of communicating
764
 * with the child process with the means of the correct
765
 * file descriptor.
766
 */
767
class Communication
768
{
769
public:
770
0
  Communication(Streams* stream): stream_(stream)
771
0
  {}
772
  Communication(const Communication&) = delete;
773
  Communication& operator=(const Communication&) = delete;
774
  Communication(Communication&&) = default;
775
  Communication& operator=(Communication&&) = default;
776
public:
777
  int send(const char* msg, size_t length);
778
  int send(const std::vector<char>& msg);
779
780
  std::pair<OutBuffer, ErrBuffer> communicate(const char* msg, size_t length);
781
  std::pair<OutBuffer, ErrBuffer> communicate(const std::vector<char>& msg)
782
0
  { return communicate(msg.data(), msg.size()); }
783
784
0
  void set_out_buf_cap(size_t cap) { out_buf_cap_ = cap; }
785
0
  void set_err_buf_cap(size_t cap) { err_buf_cap_ = cap; }
786
787
private:
788
  std::pair<OutBuffer, ErrBuffer> communicate_threaded(
789
      const char* msg, size_t length);
790
791
private:
792
  Streams* stream_;
793
  size_t out_buf_cap_ = DEFAULT_BUF_CAP_BYTES;
794
  size_t err_buf_cap_ = DEFAULT_BUF_CAP_BYTES;
795
};
796
797
798
799
/*!
800
 * This is a helper class to Popen.
801
 * It takes care of management of all the file descriptors
802
 * and file pointers.
803
 * It dispatches of the communication aspects to the
804
 * Communication class.
805
 * Read through the data members to understand about the
806
 * various file descriptors used.
807
 */
808
class Streams
809
{
810
public:
811
0
  Streams():comm_(this) {}
812
  Streams(const Streams&) = delete;
813
  Streams& operator=(const Streams&) = delete;
814
  Streams(Streams&&) = default;
815
  Streams& operator=(Streams&&) = default;
816
817
public:
818
  void setup_comm_channels();
819
820
  void cleanup_fds()
821
0
  {
822
0
    if (write_to_child_ != -1 && read_from_parent_ != -1) {
  Branch (822:9): [True: 0, False: 0]
  Branch (822:34): [True: 0, False: 0]
823
0
      subprocess_close(write_to_child_);
824
0
    }
825
0
    if (write_to_parent_ != -1 && read_from_child_ != -1) {
  Branch (825:9): [True: 0, False: 0]
  Branch (825:35): [True: 0, False: 0]
826
0
      subprocess_close(read_from_child_);
827
0
    }
828
0
    if (err_write_ != -1 && err_read_ != -1) {
  Branch (828:9): [True: 0, False: 0]
  Branch (828:29): [True: 0, False: 0]
829
0
      subprocess_close(err_read_);
830
0
    }
831
0
  }
832
833
  void close_parent_fds()
834
0
  {
835
0
    if (write_to_child_ != -1)  subprocess_close(write_to_child_);
  Branch (835:9): [True: 0, False: 0]
836
0
    if (read_from_child_ != -1) subprocess_close(read_from_child_);
  Branch (836:9): [True: 0, False: 0]
837
0
    if (err_read_ != -1)        subprocess_close(err_read_);
  Branch (837:9): [True: 0, False: 0]
838
0
  }
839
840
  void close_child_fds()
841
0
  {
842
0
    if (write_to_parent_ != -1)  subprocess_close(write_to_parent_);
  Branch (842:9): [True: 0, False: 0]
843
0
    if (read_from_parent_ != -1) subprocess_close(read_from_parent_);
  Branch (843:9): [True: 0, False: 0]
844
0
    if (err_write_ != -1)        subprocess_close(err_write_);
  Branch (844:9): [True: 0, False: 0]
845
0
  }
846
847
0
  FILE* input()  { return input_.get(); }
848
0
  FILE* output() { return output_.get(); }
849
0
  FILE* error()  { return error_.get(); }
850
851
0
  void input(FILE* fp)  { input_.reset(fp, fclose); }
852
0
  void output(FILE* fp) { output_.reset(fp, fclose); }
853
0
  void error(FILE* fp)  { error_.reset(fp, fclose); }
854
855
0
  void set_out_buf_cap(size_t cap) { comm_.set_out_buf_cap(cap); }
856
0
  void set_err_buf_cap(size_t cap) { comm_.set_err_buf_cap(cap); }
857
858
public: /* Communication forwarding API's */
859
  int send(const char* msg, size_t length)
860
0
  { return comm_.send(msg, length); }
861
862
  int send(const std::vector<char>& msg)
863
0
  { return comm_.send(msg); }
864
865
  std::pair<OutBuffer, ErrBuffer> communicate(const char* msg, size_t length)
866
0
  { return comm_.communicate(msg, length); }
867
868
  std::pair<OutBuffer, ErrBuffer> communicate(const std::vector<char>& msg)
869
0
  { return comm_.communicate(msg); }
870
871
872
public:// Yes they are public
873
874
  std::shared_ptr<FILE> input_  = nullptr;
875
  std::shared_ptr<FILE> output_ = nullptr;
876
  std::shared_ptr<FILE> error_  = nullptr;
877
878
#ifdef WIN32
879
  HANDLE g_hChildStd_IN_Rd = nullptr;
880
  HANDLE g_hChildStd_IN_Wr = nullptr;
881
  HANDLE g_hChildStd_OUT_Rd = nullptr;
882
  HANDLE g_hChildStd_OUT_Wr = nullptr;
883
  HANDLE g_hChildStd_ERR_Rd = nullptr;
884
  HANDLE g_hChildStd_ERR_Wr = nullptr;
885
#endif
886
887
  // Pipes for communicating with child
888
889
  // Emulates stdin
890
  int write_to_child_   = -1; // Parent owned descriptor
891
  int read_from_parent_ = -1; // Child owned descriptor
892
893
  // Emulates stdout
894
  int write_to_parent_ = -1; // Child owned descriptor
895
  int read_from_child_ = -1; // Parent owned descriptor
896
897
  // Emulates stderr
898
  int err_write_ = -1; // Write error to parent (Child owned)
899
  int err_read_  = -1; // Read error from child (Parent owned)
900
901
private:
902
  Communication comm_;
903
};
904
905
} // end namespace detail
906
907
908
909
/*!
910
 * class: Popen
911
 * This is the single most important class in the whole library
912
 * and glues together all the helper classes to provide a common
913
 * interface to the client.
914
 *
915
 * API's provided by the class:
916
 * Popen({"cmd"}, output{..}, error{..}, ....)
917
 *    Command provided as a sequence.
918
 * wait()             - Wait for the child to exit.
919
 * retcode()          - The return code of the exited child.
920
 * send(...)          - Send input to the input channel of the child.
921
 * communicate(...)   - Get the output/error from the child and close the channels
922
 *                      from the parent side.
923
 */
924
class Popen
925
{
926
public:
927
  friend struct detail::ArgumentDeducer;
928
#ifndef WIN32
929
  friend class detail::Child;
930
#endif
931
932
  template <typename... Args>
933
  Popen(std::initializer_list<const char*> cmd_args, Args&& ...args)
934
  {
935
    vargs_.insert(vargs_.end(), cmd_args.begin(), cmd_args.end());
936
    init_args(std::forward<Args>(args)...);
937
938
    // Setup the communication channels of the Popen class
939
    stream_.setup_comm_channels();
940
941
    execute_process();
942
  }
943
944
  template <typename... Args>
945
0
  Popen(std::vector<std::string> vargs_, Args &&... args) : vargs_(vargs_)
946
0
  {
947
0
    init_args(std::forward<Args>(args)...);
948
949
    // Setup the communication channels of the Popen class
950
0
    stream_.setup_comm_channels();
951
952
0
    execute_process();
953
0
  }
954
955
0
  int retcode() const noexcept { return retcode_; }
956
957
  int wait() noexcept(false);
958
959
0
  void set_out_buf_cap(size_t cap) { stream_.set_out_buf_cap(cap); }
960
961
0
  void set_err_buf_cap(size_t cap) { stream_.set_err_buf_cap(cap); }
962
963
  int send(const char* msg, size_t length)
964
0
  { return stream_.send(msg, length); }
965
966
  int send(const std::string& msg)
967
0
  { return send(msg.c_str(), msg.size()); }
968
969
  int send(const std::vector<char>& msg)
970
0
  { return stream_.send(msg); }
971
972
  std::pair<OutBuffer, ErrBuffer> communicate(const char* msg, size_t length)
973
0
  {
974
0
    auto res = stream_.communicate(msg, length);
975
0
    retcode_ = wait();
976
0
    return res;
977
0
  }
978
979
  std::pair<OutBuffer, ErrBuffer> communicate(const std::string& msg)
980
0
  {
981
0
    return communicate(msg.c_str(), msg.size());
982
0
  }
983
984
  std::pair<OutBuffer, ErrBuffer> communicate(const std::vector<char>& msg)
985
0
  {
986
0
    auto res = stream_.communicate(msg);
987
0
    retcode_ = wait();
988
0
    return res;
989
0
  }
990
991
  std::pair<OutBuffer, ErrBuffer> communicate()
992
0
  {
993
0
    return communicate(nullptr, 0);
994
0
  }
995
996
private:
997
  template <typename F, typename... Args>
998
  void init_args(F&& farg, Args&&... args);
999
  void init_args();
1000
  void populate_c_argv();
1001
  void execute_process() noexcept(false);
1002
1003
private:
1004
  detail::Streams stream_;
1005
1006
#ifdef WIN32
1007
  HANDLE process_handle_;
1008
  std::future<void> cleanup_future_;
1009
#else
1010
  // Pid of the child process
1011
  int child_pid_ = -1;
1012
#endif
1013
1014
  std::string exe_name_;
1015
1016
  // Command provided as sequence
1017
  std::vector<std::string> vargs_;
1018
  std::vector<char*> cargv_;
1019
1020
  int retcode_ = -1;
1021
};
1022
1023
0
inline void Popen::init_args() {
1024
0
  populate_c_argv();
1025
0
}
1026
1027
template <typename F, typename... Args>
1028
inline void Popen::init_args(F&& farg, Args&&... args)
1029
0
{
1030
0
  detail::ArgumentDeducer argd(this);
1031
0
  argd.set_option(std::forward<F>(farg));
1032
0
  init_args(std::forward<Args>(args)...);
1033
0
}
Unexecuted instantiation: _ZN10subprocess5Popen9init_argsINS_5inputEJNS_6outputENS_5errorEEEEvOT_DpOT0_
Unexecuted instantiation: _ZN10subprocess5Popen9init_argsINS_6outputEJNS_5errorEEEEvOT_DpOT0_
Unexecuted instantiation: _ZN10subprocess5Popen9init_argsINS_5errorEJEEEvOT_DpOT0_
1034
1035
inline void Popen::populate_c_argv()
1036
0
{
1037
0
  cargv_.clear();
1038
0
  cargv_.reserve(vargs_.size() + 1);
1039
0
  for (auto& arg : vargs_) cargv_.push_back(&arg[0]);
  Branch (1039:18): [True: 0, False: 0]
1040
0
  cargv_.push_back(nullptr);
1041
0
}
1042
1043
inline int Popen::wait() noexcept(false)
1044
0
{
1045
#ifdef WIN32
1046
  int ret = WaitForSingleObject(process_handle_, INFINITE);
1047
1048
  // WaitForSingleObject with INFINITE should only return when process has signaled
1049
  if (ret != WAIT_OBJECT_0) {
1050
    throw OSError("Unexpected return code from WaitForSingleObject", 0);
1051
  }
1052
1053
  DWORD dretcode_;
1054
1055
  if (FALSE == GetExitCodeProcess(process_handle_, &dretcode_))
1056
      throw OSError("Failed during call to GetExitCodeProcess", 0);
1057
1058
  CloseHandle(process_handle_);
1059
1060
  return (int)dretcode_;
1061
#else
1062
0
  int ret, status;
1063
0
  std::tie(ret, status) = util::wait_for_child_exit(child_pid_);
1064
0
  if (ret == -1) {
  Branch (1064:7): [True: 0, False: 0]
1065
0
    if (errno != ECHILD) throw OSError("waitpid failed", errno);
  Branch (1065:9): [True: 0, False: 0]
1066
0
    return 0;
1067
0
  }
1068
0
  if (WIFEXITED(status)) return WEXITSTATUS(status);
  Branch (1068:7): [True: 0, False: 0]
1069
0
  if (WIFSIGNALED(status)) return WTERMSIG(status);
  Branch (1069:7): [True: 0, False: 0]
1070
0
  else return 255;
1071
1072
0
  return 0;
1073
0
#endif
1074
0
}
1075
1076
inline void Popen::execute_process() noexcept(false)
1077
0
{
1078
#ifdef WIN32
1079
  if (exe_name_.length()) {
1080
    this->vargs_.insert(this->vargs_.begin(), this->exe_name_);
1081
    this->populate_c_argv();
1082
  }
1083
  this->exe_name_ = vargs_[0];
1084
1085
  std::string argument;
1086
  std::string command_line;
1087
  bool first_arg = true;
1088
1089
  for (auto arg : this->vargs_) {
1090
    if (!first_arg) {
1091
      command_line += " ";
1092
    } else {
1093
      first_arg = false;
1094
    }
1095
    argument = arg;
1096
    util::quote_argument(argument, command_line, /*force=*/false);
1097
  }
1098
1099
  // CreateProcessA can modify szCmdLine so we allocate needed memory
1100
  char *szCmdline = new char[command_line.size() + 1];
1101
  strcpy_s(szCmdline, command_line.size() + 1, command_line.c_str());
1102
  PROCESS_INFORMATION piProcInfo;
1103
  STARTUPINFOA siStartInfo;
1104
  BOOL bSuccess = FALSE;
1105
  DWORD creation_flags = CREATE_NO_WINDOW;
1106
1107
  // Set up members of the PROCESS_INFORMATION structure.
1108
  ZeroMemory(&piProcInfo, sizeof(PROCESS_INFORMATION));
1109
1110
  // Set up members of the STARTUPINFOA structure.
1111
  // This structure specifies the STDIN and STDOUT handles for redirection.
1112
1113
  ZeroMemory(&siStartInfo, sizeof(STARTUPINFOA));
1114
  siStartInfo.cb = sizeof(STARTUPINFOA);
1115
1116
  siStartInfo.hStdError = this->stream_.g_hChildStd_ERR_Wr;
1117
  siStartInfo.hStdOutput = this->stream_.g_hChildStd_OUT_Wr;
1118
  siStartInfo.hStdInput = this->stream_.g_hChildStd_IN_Rd;
1119
1120
  siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
1121
1122
  // Create the child process.
1123
  bSuccess = CreateProcessA(NULL,
1124
                            szCmdline,    // command line
1125
                            NULL,         // process security attributes
1126
                            NULL,         // primary thread security attributes
1127
                            TRUE,         // handles are inherited
1128
                            creation_flags, // creation flags
1129
                            NULL,         // use parent's environment
1130
                            NULL,         // use parent's current directory
1131
                            &siStartInfo, // STARTUPINFOA pointer
1132
                            &piProcInfo); // receives PROCESS_INFORMATION
1133
1134
  // If an error occurs, exit the application.
1135
  if (!bSuccess) {
1136
    DWORD errorMessageID = ::GetLastError();
1137
    throw CalledProcessError("CreateProcess failed: " + util::get_last_error(errorMessageID), errorMessageID);
1138
  }
1139
1140
  CloseHandle(piProcInfo.hThread);
1141
1142
  /*
1143
    TODO: use common apis to close linux handles
1144
  */
1145
1146
  this->process_handle_ = piProcInfo.hProcess;
1147
1148
  this->cleanup_future_ = std::async(std::launch::async, [this] {
1149
    WaitForSingleObject(this->process_handle_, INFINITE);
1150
1151
    CloseHandle(this->stream_.g_hChildStd_ERR_Wr);
1152
    CloseHandle(this->stream_.g_hChildStd_OUT_Wr);
1153
    CloseHandle(this->stream_.g_hChildStd_IN_Rd);
1154
  });
1155
1156
/*
1157
  NOTE: In the linux version, there is a check to make sure that the process
1158
        has been started. Here, we do nothing because CreateProcess will throw
1159
        if we fail to create the process.
1160
*/
1161
1162
1163
#else
1164
1165
0
  int err_rd_pipe, err_wr_pipe;
1166
0
  std::tie(err_rd_pipe, err_wr_pipe) = util::pipe_cloexec();
1167
1168
0
  if (exe_name_.length()) {
  Branch (1168:7): [True: 0, False: 0]
1169
0
    vargs_.insert(vargs_.begin(), exe_name_);
1170
0
    populate_c_argv();
1171
0
  }
1172
0
  exe_name_ = vargs_[0];
1173
1174
0
  child_pid_ = fork();
1175
1176
0
  if (child_pid_ < 0) {
  Branch (1176:7): [True: 0, False: 0]
1177
0
    subprocess_close(err_rd_pipe);
1178
0
    subprocess_close(err_wr_pipe);
1179
0
    throw OSError("fork failed", errno);
1180
0
  }
1181
1182
0
  if (child_pid_ == 0)
  Branch (1182:7): [True: 0, False: 0]
1183
0
  {
1184
    // Close descriptors belonging to parent
1185
0
    stream_.close_parent_fds();
1186
1187
    //Close the read end of the error pipe
1188
0
    subprocess_close(err_rd_pipe);
1189
1190
0
    detail::Child chld(this, err_wr_pipe);
1191
0
    chld.execute_child();
1192
0
  }
1193
0
  else
1194
0
  {
1195
0
    subprocess_close(err_wr_pipe);// close child side of pipe, else get stuck in read below
1196
1197
0
    stream_.close_child_fds();
1198
1199
0
    try {
1200
0
      char err_buf[SP_MAX_ERR_BUF_SIZ] = {0,};
1201
1202
0
      FILE* err_fp = fdopen(err_rd_pipe, "r");
1203
0
      if (!err_fp) {
  Branch (1203:11): [True: 0, False: 0]
1204
0
          subprocess_close(err_rd_pipe);
1205
0
          throw OSError("fdopen failed", errno);
1206
0
      }
1207
0
      int read_bytes = util::read_atmost_n(err_fp, err_buf, SP_MAX_ERR_BUF_SIZ);
1208
0
      fclose(err_fp);
1209
1210
0
      if (read_bytes || strlen(err_buf)) {
  Branch (1210:11): [True: 0, False: 0]
  Branch (1210:25): [True: 0, False: 0]
1211
        // Call waitpid to reap the child process
1212
        // waitpid suspends the calling process until the
1213
        // child terminates.
1214
0
        int retcode = wait();
1215
1216
        // Throw whatever information we have about child failure
1217
0
        throw CalledProcessError(err_buf, retcode);
1218
0
      }
1219
0
    } catch (std::exception& exp) {
1220
0
      stream_.cleanup_fds();
1221
0
      throw;
1222
0
    }
1223
1224
0
  }
1225
0
#endif
1226
0
}
1227
1228
namespace detail {
1229
1230
0
  inline void ArgumentDeducer::set_option(executable&& exe) {
1231
0
    popen_->exe_name_ = std::move(exe.arg_value);
1232
0
  }
1233
1234
0
  inline void ArgumentDeducer::set_option(input&& inp) {
1235
0
    if (inp.rd_ch_ != -1) popen_->stream_.read_from_parent_ = inp.rd_ch_;
  Branch (1235:9): [True: 0, False: 0]
1236
0
    if (inp.wr_ch_ != -1) popen_->stream_.write_to_child_ = inp.wr_ch_;
  Branch (1236:9): [True: 0, False: 0]
1237
0
  }
1238
1239
0
  inline void ArgumentDeducer::set_option(output&& out) {
1240
0
    if (out.wr_ch_ != -1) popen_->stream_.write_to_parent_ = out.wr_ch_;
  Branch (1240:9): [True: 0, False: 0]
1241
0
    if (out.rd_ch_ != -1) popen_->stream_.read_from_child_ = out.rd_ch_;
  Branch (1241:9): [True: 0, False: 0]
1242
0
  }
1243
1244
0
  inline void ArgumentDeducer::set_option(error&& err) {
1245
0
    if (err.deferred_) {
  Branch (1245:9): [True: 0, False: 0]
1246
0
      if (popen_->stream_.write_to_parent_) {
  Branch (1246:11): [True: 0, False: 0]
1247
0
        popen_->stream_.err_write_ = popen_->stream_.write_to_parent_;
1248
0
      } else {
1249
0
        throw std::runtime_error("Set output before redirecting error to output");
1250
0
      }
1251
0
    }
1252
0
    if (err.wr_ch_ != -1) popen_->stream_.err_write_ = err.wr_ch_;
  Branch (1252:9): [True: 0, False: 0]
1253
0
    if (err.rd_ch_ != -1) popen_->stream_.err_read_ = err.rd_ch_;
  Branch (1253:9): [True: 0, False: 0]
1254
0
  }
1255
1256
1257
#ifndef WIN32
1258
0
  inline void Child::execute_child() {
1259
0
    int sys_ret = -1;
1260
0
    auto& stream = parent_->stream_;
1261
1262
0
    try {
1263
0
      if (stream.write_to_parent_ == 0)
  Branch (1263:11): [True: 0, False: 0]
1264
0
        stream.write_to_parent_ = dup(stream.write_to_parent_);
1265
1266
0
      if (stream.err_write_ == 0 || stream.err_write_ == 1)
  Branch (1266:11): [True: 0, False: 0]
  Branch (1266:37): [True: 0, False: 0]
1267
0
        stream.err_write_ = dup(stream.err_write_);
1268
1269
      // Make the child owned descriptors as the
1270
      // stdin, stdout and stderr for the child process
1271
0
      auto _dup2_ = [](int fd, int to_fd) {
1272
0
        if (fd == to_fd) {
  Branch (1272:13): [True: 0, False: 0]
1273
          // dup2 syscall does not reset the
1274
          // CLOEXEC flag if the descriptors
1275
          // provided to it are same.
1276
          // But, we need to reset the CLOEXEC
1277
          // flag as the provided descriptors
1278
          // are now going to be the standard
1279
          // input, output and error
1280
0
          util::set_clo_on_exec(fd, false);
1281
0
        } else if(fd != -1) {
  Branch (1281:19): [True: 0, False: 0]
1282
0
          int res = dup2(fd, to_fd);
1283
0
          if (res == -1) throw OSError("dup2 failed", errno);
  Branch (1283:15): [True: 0, False: 0]
1284
0
        }
1285
0
      };
1286
1287
      // Create the standard streams
1288
0
      _dup2_(stream.read_from_parent_, 0); // Input stream
1289
0
      _dup2_(stream.write_to_parent_,  1); // Output stream
1290
0
      _dup2_(stream.err_write_,        2); // Error stream
1291
1292
      // Close the duped descriptors
1293
0
      if (stream.read_from_parent_ != -1 && stream.read_from_parent_ > 2)
  Branch (1293:11): [True: 0, False: 0]
  Branch (1293:45): [True: 0, False: 0]
1294
0
        subprocess_close(stream.read_from_parent_);
1295
1296
0
      if (stream.write_to_parent_ != -1 && stream.write_to_parent_ > 2)
  Branch (1296:11): [True: 0, False: 0]
  Branch (1296:44): [True: 0, False: 0]
1297
0
        subprocess_close(stream.write_to_parent_);
1298
1299
0
      if (stream.err_write_ != -1 && stream.err_write_ > 2)
  Branch (1299:11): [True: 0, False: 0]
  Branch (1299:38): [True: 0, False: 0]
1300
0
        subprocess_close(stream.err_write_);
1301
1302
      // Replace the current image with the executable
1303
0
      sys_ret = execvp(parent_->exe_name_.c_str(), parent_->cargv_.data());
1304
1305
0
      if (sys_ret == -1) throw OSError("execve failed", errno);
  Branch (1305:11): [True: 0, False: 0]
1306
1307
0
    } catch (const OSError& exp) {
1308
      // Just write the exception message
1309
      // TODO: Give back stack trace ?
1310
0
      std::string err_msg(exp.what());
1311
      //ATTN: Can we do something on error here ?
1312
0
      util::write_n(err_wr_pipe_, err_msg.c_str(), err_msg.length());
1313
0
    }
1314
1315
    // Calling application would not get this
1316
    // exit failure
1317
0
    _exit (EXIT_FAILURE);
1318
0
  }
1319
#endif
1320
1321
1322
  inline void Streams::setup_comm_channels()
1323
0
  {
1324
#ifdef WIN32
1325
    util::configure_pipe(&this->g_hChildStd_IN_Rd, &this->g_hChildStd_IN_Wr, &this->g_hChildStd_IN_Wr);
1326
    this->input(util::file_from_handle(this->g_hChildStd_IN_Wr, "w"));
1327
    this->write_to_child_ = subprocess_fileno(this->input());
1328
1329
    util::configure_pipe(&this->g_hChildStd_OUT_Rd, &this->g_hChildStd_OUT_Wr, &this->g_hChildStd_OUT_Rd);
1330
    this->output(util::file_from_handle(this->g_hChildStd_OUT_Rd, "r"));
1331
    this->read_from_child_ = subprocess_fileno(this->output());
1332
1333
    util::configure_pipe(&this->g_hChildStd_ERR_Rd, &this->g_hChildStd_ERR_Wr, &this->g_hChildStd_ERR_Rd);
1334
    this->error(util::file_from_handle(this->g_hChildStd_ERR_Rd, "r"));
1335
    this->err_read_ = subprocess_fileno(this->error());
1336
#else
1337
1338
0
    if (write_to_child_ != -1)  input(fdopen(write_to_child_, "wb"));
  Branch (1338:9): [True: 0, False: 0]
1339
0
    if (read_from_child_ != -1) output(fdopen(read_from_child_, "rb"));
  Branch (1339:9): [True: 0, False: 0]
1340
0
    if (err_read_ != -1)        error(fdopen(err_read_, "rb"));
  Branch (1340:9): [True: 0, False: 0]
1341
1342
0
    auto handles = {input(), output(), error()};
1343
1344
0
    for (auto& h : handles) {
  Branch (1344:18): [True: 0, False: 0]
1345
0
      if (h == nullptr) continue;
  Branch (1345:11): [True: 0, False: 0]
1346
0
      setvbuf(h, nullptr, _IONBF, BUFSIZ);
1347
0
    }
1348
0
  #endif
1349
0
  }
1350
1351
  inline int Communication::send(const char* msg, size_t length)
1352
0
  {
1353
0
    if (stream_->input() == nullptr) return -1;
  Branch (1353:9): [True: 0, False: 0]
1354
0
    return std::fwrite(msg, sizeof(char), length, stream_->input());
1355
0
  }
1356
1357
  inline int Communication::send(const std::vector<char>& msg)
1358
0
  {
1359
0
    return send(msg.data(), msg.size());
1360
0
  }
1361
1362
  inline std::pair<OutBuffer, ErrBuffer>
1363
  Communication::communicate(const char* msg, size_t length)
1364
0
  {
1365
    // Optimization from subprocess.py
1366
    // If we are using one pipe, or no pipe
1367
    // at all, using select() or threads is unnecessary.
1368
0
    auto hndls = {stream_->input(), stream_->output(), stream_->error()};
1369
0
    int count = std::count(std::begin(hndls), std::end(hndls), nullptr);
1370
0
    const int len_conv = length;
1371
1372
0
    if (count >= 2) {
  Branch (1372:9): [True: 0, False: 0]
1373
0
      OutBuffer obuf;
1374
0
      ErrBuffer ebuf;
1375
0
      if (stream_->input()) {
  Branch (1375:11): [True: 0, False: 0]
1376
0
        if (msg) {
  Branch (1376:13): [True: 0, False: 0]
1377
0
          int wbytes = std::fwrite(msg, sizeof(char), length, stream_->input());
1378
0
          if (wbytes < len_conv) {
  Branch (1378:15): [True: 0, False: 0]
1379
0
            if (errno != EPIPE && errno != EINVAL) {
  Branch (1379:17): [True: 0, False: 0]
  Branch (1379:35): [True: 0, False: 0]
1380
0
              throw OSError("fwrite error", errno);
1381
0
            }
1382
0
          }
1383
0
        }
1384
        // Close the input stream
1385
0
        stream_->input_.reset();
1386
0
      } else if (stream_->output()) {
  Branch (1386:18): [True: 0, False: 0]
1387
        // Read till EOF
1388
        // ATTN: This could be blocking, if the process
1389
        // at the other end screws up, we get screwed as well
1390
0
        obuf.add_cap(out_buf_cap_);
1391
1392
0
        int rbytes = util::read_all(
1393
0
                            stream_->output(),
1394
0
                            obuf.buf);
1395
1396
0
        if (rbytes == -1) {
  Branch (1396:13): [True: 0, False: 0]
1397
0
          throw OSError("read to obuf failed", errno);
1398
0
        }
1399
1400
0
        obuf.length = rbytes;
1401
        // Close the output stream
1402
0
        stream_->output_.reset();
1403
1404
0
      } else if (stream_->error()) {
  Branch (1404:18): [True: 0, False: 0]
1405
        // Same screwness applies here as well
1406
0
        ebuf.add_cap(err_buf_cap_);
1407
1408
0
        int rbytes = util::read_atmost_n(
1409
0
                                  stream_->error(),
1410
0
                                  ebuf.buf.data(),
1411
0
                                  ebuf.buf.size());
1412
1413
0
        if (rbytes == -1) {
  Branch (1413:13): [True: 0, False: 0]
1414
0
          throw OSError("read to ebuf failed", errno);
1415
0
        }
1416
1417
0
        ebuf.length = rbytes;
1418
        // Close the error stream
1419
0
        stream_->error_.reset();
1420
0
      }
1421
0
      return std::make_pair(std::move(obuf), std::move(ebuf));
1422
0
    }
1423
1424
0
    return communicate_threaded(msg, length);
1425
0
  }
1426
1427
1428
  inline std::pair<OutBuffer, ErrBuffer>
1429
  Communication::communicate_threaded(const char* msg, size_t length)
1430
0
  {
1431
0
    OutBuffer obuf;
1432
0
    ErrBuffer ebuf;
1433
0
    std::future<int> out_fut, err_fut;
1434
0
    const int length_conv = length;
1435
1436
0
    if (stream_->output()) {
  Branch (1436:9): [True: 0, False: 0]
1437
0
      obuf.add_cap(out_buf_cap_);
1438
1439
0
      out_fut = std::async(std::launch::async,
1440
0
                          [&obuf, this] {
1441
0
                            return util::read_all(this->stream_->output(), obuf.buf);
1442
0
                          });
1443
0
    }
1444
0
    if (stream_->error()) {
  Branch (1444:9): [True: 0, False: 0]
1445
0
      ebuf.add_cap(err_buf_cap_);
1446
1447
0
      err_fut = std::async(std::launch::async,
1448
0
                          [&ebuf, this] {
1449
0
                            return util::read_all(this->stream_->error(), ebuf.buf);
1450
0
                          });
1451
0
    }
1452
0
    if (stream_->input()) {
  Branch (1452:9): [True: 0, False: 0]
1453
0
      if (msg) {
  Branch (1453:11): [True: 0, False: 0]
1454
0
        int wbytes = std::fwrite(msg, sizeof(char), length, stream_->input());
1455
0
        if (wbytes < length_conv) {
  Branch (1455:13): [True: 0, False: 0]
1456
0
          if (errno != EPIPE && errno != EINVAL) {
  Branch (1456:15): [True: 0, False: 0]
  Branch (1456:33): [True: 0, False: 0]
1457
0
            throw OSError("fwrite error", errno);
1458
0
          }
1459
0
        }
1460
0
      }
1461
0
      stream_->input_.reset();
1462
0
    }
1463
1464
0
    if (out_fut.valid()) {
  Branch (1464:9): [True: 0, False: 0]
1465
0
      int res = out_fut.get();
1466
0
      if (res != -1) obuf.length = res;
  Branch (1466:11): [True: 0, False: 0]
1467
0
      else obuf.length = 0;
1468
0
    }
1469
0
    if (err_fut.valid()) {
  Branch (1469:9): [True: 0, False: 0]
1470
0
      int res = err_fut.get();
1471
0
      if (res != -1) ebuf.length = res;
  Branch (1471:11): [True: 0, False: 0]
1472
0
      else ebuf.length = 0;
1473
0
    }
1474
1475
0
    return std::make_pair(std::move(obuf), std::move(ebuf));
1476
0
  }
1477
1478
} // end namespace detail
1479
1480
}
1481
1482
#endif // BITCOIN_UTIL_SUBPROCESS_H