Arcane  4.2.1.0
Developer documentation
Loading...
Searching...
No Matches
Process.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2026 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4// See the top-level COPYRIGHT file for details.
5// SPDX-License-Identifier: Apache-2.0
6//-----------------------------------------------------------------------------
7/*---------------------------------------------------------------------------*/
8/* Process.cc (C) 2000-2026 */
9/* */
10/* Process management. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arccore/common/internal/Process.h"
15
16#include "arccore/base/NotImplementedException.h"
17#include "arccore/base/FixedArray.h"
18
19#include <iostream>
20
21/*
22 * NOTE: for now this class is only implemented for Linux
23 * (it should however work with other Unix systems).
24 */
25
26#ifdef ARCCORE_OS_LINUX
27#include <unistd.h>
28#include <sys/wait.h>
29#include <fcntl.h>
30#endif
31
32/*---------------------------------------------------------------------------*/
33/*---------------------------------------------------------------------------*/
34
35namespace Arcane
36{
37
38/*---------------------------------------------------------------------------*/
39/*---------------------------------------------------------------------------*/
40
43{
44#ifdef ARCCORE_OS_LINUX
45 args.m_output_bytes.clear();
46 ByteConstArrayView input_bytes = args.inputBytes();
47
48 // Create two pipes to redirect the inputs and outputs of the
49 // process we are going to launch.
50 int pipefd_out[2];
51 int pipefd_in[2];
52 int r0 = pipe2(pipefd_out, O_CLOEXEC);
53 if (r0 != 0)
55 r0 = pipe2(pipefd_in, O_CLOEXEC);
56 if (r0 != 0)
58 pid_t cpid = ::fork();
59 if (cpid < 0)
61
62 ProcessExecArgs::ExecStatus exec_status = ProcessExecArgs::ExecStatus::OK;
63 if (cpid == 0) {
64 // I am the child process.
65
66 // TODO: check errors for close() and dup2().
67
68 // Indicates that pipefd_out[1] corresponds to my STDOUT
69 ::close(STDOUT_FILENO);
70 ::close(pipefd_out[0]);
71 ::dup2(pipefd_out[1], STDOUT_FILENO);
72
73 // Indicates that pipefd_in[0] corresponds to my STDIN
74 ::close(STDIN_FILENO);
75 ::close(pipefd_in[1]);
76 ::dup2(pipefd_in[0], STDIN_FILENO);
77
78 const char* cmd_name = args.command().localstr();
79
80 ConstArrayView<String> arguments = args.arguments();
81 Integer nb_arg = arguments.size();
82 // The array passed to execve() for arguments must end with NULL
83 // and start with the name of the executable
84 UniqueArray<const char*> command_args(nb_arg + 2);
85 for (Integer i = 0; i < nb_arg; ++i)
86 command_args[i + 1] = arguments[i].localstr();
87 command_args[0] = cmd_name;
88 command_args[nb_arg + 1] = nullptr;
89
90 const char* const newenviron[] = { NULL };
91 ::execve(cmd_name, (char* const*)command_args.data(), (char* const*)newenviron);
92 // The execve() call does not return.
93 }
94 else {
95 ::close(pipefd_out[1]);
96 ::close(pipefd_in[0]);
97 // Write the bytes of \a input_bytes to the input pipe
98 Int64 nb_wanted_write = input_bytes.size();
99 Int64 nb_written = ::write(pipefd_in[1], input_bytes.data(), nb_wanted_write);
100 if (nb_written != nb_wanted_write)
101 std::cerr << "Error writing to pipe\n";
102 ::close(pipefd_in[1]);
103 const int BUF_SIZE = 4096;
105 buf[BUF_SIZE] = '\0';
106 Int32 max_iteration = 1000000;
107 Int32 current_iteration = 0;
108 // Uses a finite loop to avoid coverity/codacy warnings
109 for (Int32 i = 0; i < max_iteration; ++i) {
110 ssize_t nb_read = ::read(pipefd_out[0], buf.data(), BUF_SIZE);
111 if (nb_read == EINTR)
112 continue;
113 if (nb_read <= 0)
114 break;
115 Int32 i_nb_read = static_cast<Int32>(nb_read);
116 buf[i_nb_read] = '\0';
117 args.m_output_bytes.addRange(buf.view().subView(0, i_nb_read));
118 //::write(STDOUT_FILENO, buf, r);
119 }
120
121 // Wait for the child process to finish.
122 int status = 0;
123 pid_t child_pid = 0;
124 do {
125 child_pid = ::waitpid(cpid, &status, 0); /* Wait for child */
126 } while (child_pid == -1 && errno == EINTR);
127
128 if (WIFEXITED(status)) {
129 args.m_exit_code = WEXITSTATUS(status);
130 //printf("exited, status=%d\n", WEXITSTATUS(status));
131 }
132 else
133 exec_status = ProcessExecArgs::ExecStatus::AbnormalExit;
134
135 close(pipefd_out[0]);
136
137 // Adds a terminal '\0' to the output stream.
138 args.m_output_bytes.add('\0');
139 }
140 return exec_status;
141#else
142 throw NotImplementedException(A_FUNCINFO);
143#endif
144}
145
146/*---------------------------------------------------------------------------*/
147/*---------------------------------------------------------------------------*/
148
149} // namespace Arcane
150
151/*---------------------------------------------------------------------------*/
152/*---------------------------------------------------------------------------*/
void addRange(ConstReferenceType val, Int64 n)
Adds n elements of value val to the end of the array.
void clear()
Removes the elements from the array.
void add(ConstReferenceType val)
Adds element val to the end of the array.
const T * data() const
Access to the root of the array without any protection.
Constant view of an array of type T.
constexpr const_pointer data() const noexcept
Pointer to the allocated memory.
constexpr Integer size() const noexcept
Number of elements in the array.
constexpr __host__ __device__ ArrayView< T > view()
Modifiable view of the array.
@ CanNotCreatePipe
The call to pipe2() failed.
Definition Process.h:43
ConstArrayView< String > arguments() const
List of arguments.
Definition Process.h:55
String command() const
Command to execute. Must correspond to an executable.
Definition Process.h:51
ConstArrayView< Byte > inputBytes() const
String to send to the process's standard input (STDIN).
Definition Process.h:60
static ProcessExecArgs::ExecStatus execute(ProcessExecArgs &args)
Executes a process whose information is contained in args.
Definition Process.cc:42
const char * localstr() const
Returns the conversion of the instance into UTF-8 encoding.
Definition String.cc:229
1D data vector with value semantics (STL style).
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
std::int64_t Int64
Signed integer type of 64 bits.
Int32 Integer
Type representing an integer.
ConstArrayView< Byte > ByteConstArrayView
C equivalent of a 1D array of characters.
Definition UtilsTypes.h:470
std::int32_t Int32
Signed integer type of 32 bits.