Arcane  4.1.12.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-2025 */
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/*
20 * NOTE: for now this class is only implemented for Linux
21 * (it should however work with other Unix systems).
22 */
23
24#ifdef ARCCORE_OS_LINUX
25#include <unistd.h>
26#include <sys/wait.h>
27#include <fcntl.h>
28#endif
29
30/*---------------------------------------------------------------------------*/
31/*---------------------------------------------------------------------------*/
32
33namespace Arcane
34{
35
36/*---------------------------------------------------------------------------*/
37/*---------------------------------------------------------------------------*/
38
41{
42#ifdef ARCCORE_OS_LINUX
43 args.m_output_bytes.clear();
44 ByteConstArrayView input_bytes = args.inputBytes();
45
46 // Create two pipes to redirect the inputs and outputs of the
47 // process we are going to launch.
48 int pipefd_out[2];
49 int pipefd_in[2];
50 int r0 = pipe2(pipefd_out, O_CLOEXEC);
51 if (r0 != 0)
53 r0 = pipe2(pipefd_in, O_CLOEXEC);
54 if (r0 != 0)
56 pid_t cpid = ::fork();
57 if (cpid < 0)
59
60 ProcessExecArgs::ExecStatus exec_status = ProcessExecArgs::ExecStatus::OK;
61 if (cpid == 0) {
62 // I am the child process.
63
64 // TODO: check errors for close() and dup2().
65
66 // Indicates that pipefd_out[1] corresponds to my STDOUT
67 ::close(STDOUT_FILENO);
68 ::close(pipefd_out[0]);
69 ::dup2(pipefd_out[1], STDOUT_FILENO);
70
71 // Indicates that pipefd_in[0] corresponds to my STDIN
72 ::close(STDIN_FILENO);
73 ::close(pipefd_in[1]);
74 ::dup2(pipefd_in[0], STDIN_FILENO);
75
76 const char* cmd_name = args.command().localstr();
77
78 ConstArrayView<String> arguments = args.arguments();
79 Integer nb_arg = arguments.size();
80 // The array passed to execve() for arguments must end with NULL
81 // and start with the name of the executable
82 UniqueArray<const char*> command_args(nb_arg + 2);
83 for (Integer i = 0; i < nb_arg; ++i)
84 command_args[i + 1] = arguments[i].localstr();
85 command_args[0] = cmd_name;
86 command_args[nb_arg + 1] = nullptr;
87
88 const char* const newenviron[] = { NULL };
89 ::execve(cmd_name, (char* const*)command_args.data(), (char* const*)newenviron);
90 // The execve() call does not return.
91 }
92 else {
93 ::close(pipefd_out[1]);
94 ::close(pipefd_in[0]);
95 // Write the bytes of \a input_bytes to the input pipe
96 Int64 nb_wanted_write = input_bytes.size();
97 Int64 nb_written = ::write(pipefd_in[1], input_bytes.data(), nb_wanted_write);
98 if (nb_written != nb_wanted_write)
99 std::cerr << "Error writing to pipe\n";
100 ::close(pipefd_in[1]);
101 const int BUF_SIZE = 4096;
103 buf[BUF_SIZE] = '\0';
104 Int32 max_iteration = 1000000;
105 Int32 current_iteration = 0;
106 // Uses a finite loop to avoid coverity/codacy warnings
107 for (Int32 i = 0; i < max_iteration; ++i) {
108 ssize_t nb_read = ::read(pipefd_out[0], buf.data(), BUF_SIZE);
109 if (nb_read == EINTR)
110 continue;
111 if (nb_read <= 0)
112 break;
113 Int32 i_nb_read = static_cast<Int32>(nb_read);
114 buf[i_nb_read] = '\0';
115 args.m_output_bytes.addRange(buf.view().subView(0, i_nb_read));
116 //::write(STDOUT_FILENO, buf, r);
117 }
118
119 // Wait for the child process to finish.
120 int status = 0;
121 pid_t child_pid = 0;
122 do {
123 child_pid = ::waitpid(cpid, &status, 0); /* Wait for child */
124 } while (child_pid == -1 && errno == EINTR);
125
126 if (WIFEXITED(status)) {
127 args.m_exit_code = WEXITSTATUS(status);
128 //printf("exited, status=%d\n", WEXITSTATUS(status));
129 }
130 else
131 exec_status = ProcessExecArgs::ExecStatus::AbnormalExit;
132
133 close(pipefd_out[0]);
134
135 // Adds a terminal '\0' to the output stream.
136 args.m_output_bytes.add('\0');
137 }
138 return exec_status;
139#else
140 throw NotImplementedException(A_FUNCINFO);
141#endif
142}
143
144/*---------------------------------------------------------------------------*/
145/*---------------------------------------------------------------------------*/
146
147} // namespace Arcane
148
149/*---------------------------------------------------------------------------*/
150/*---------------------------------------------------------------------------*/
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:40
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:476
std::int32_t Int32
Signed integer type of 32 bits.