Coverage Report

Created: 2025-06-10 13:21

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