Coverage Report

Created: 2026-04-29 19:21

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