Arcane  4.2.1.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
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/* Gestion des processus. */
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: pour l'instant cette classe n'est implémentée que pour Linux
23 * (elle devrait cependant fonctionner avec les autres Unix).
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 // Créé deux pipes pour rediriger les entrées et les sorties du
49 // processus qu'on va lancer.
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 // Je suis le processus fils.
65
66 // TODO: vérifier les erreurs des close() et dup2().
67
68 // Indique que pipefd_out[1] correspond à mon STDOUT
69 ::close(STDOUT_FILENO);
70 ::close(pipefd_out[0]);
71 ::dup2(pipefd_out[1], STDOUT_FILENO);
72
73 // Indique que pipefd_in[0] correspond à mon 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 // Le tableau passé à execve() pour les arguments doit se terminer par NULL
83 // et commencer par le nom de l'exécutable
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 // L'appel à execve() ne retourne pas.
93 }
94 else {
95 ::close(pipefd_out[1]);
96 ::close(pipefd_in[0]);
97 // Ecrit sur le pipe d'entrée les octets de \a input_bytes
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 // Utilise une boucle finie pour éviter les avertissements de coverity/codacy
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 // Attend que le processus fils soit fini.
122 int status = 0;
123 pid_t child_pid = 0;
124 do {
125 child_pid = ::waitpid(cpid, &status, 0); /* Attendre l'enfant */
126 } while (child_pid == -1 && errno == EINTR);
127
128 if (WIFEXITED(status)) {
129 args.m_exit_code = WEXITSTATUS(status);
130 //printf("terminé, statut=%d\n", WEXITSTATUS(status));
131 }
132 else
133 exec_status = ProcessExecArgs::ExecStatus::AbnormalExit;
134
135 close(pipefd_out[0]);
136
137 // Ajoute un '\0' terminal au flux de sortie.
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 clear()
Supprime les éléments du tableau.
const T * data() const
Accès à la racine du tableau hors toute protection.
void addRange(ConstReferenceType val, Int64 n)
Ajoute n élément de valeur val à la fin du tableau.
void add(ConstReferenceType val)
Ajoute l'élément val à la fin du tableau.
Vue constante d'un tableau de type T.
constexpr const_pointer data() const noexcept
Pointeur sur la mémoire allouée.
constexpr Integer size() const noexcept
Nombre d'éléments du tableau.
constexpr __host__ __device__ ArrayView< T > view()
Vue modifiable sur le tableau.
Exception lorsqu'une fonction n'est pas implémentée.
@ CanNotFork
Le fork() a échoué
Definition Process.h:41
@ CanNotCreatePipe
L'appel à pipe2() a échoué
Definition Process.h:43
ConstArrayView< String > arguments() const
Liste des arguments.
Definition Process.h:55
String command() const
Commande à exécuter. Doit correspondre à un exécutable.
Definition Process.h:51
ConstArrayView< Byte > inputBytes() const
Chaîne de caractères à envoyer sur l'entrée standard (STDIN) du processsus.
Definition Process.h:60
static ProcessExecArgs::ExecStatus execute(ProcessExecArgs &args)
Exécute un processus dont les infos sont contenues dans args.
Definition Process.cc:42
const char * localstr() const
Retourne la conversion de l'instance dans l'encodage UTF-8.
Definition String.cc:228
Vecteur 1D de données avec sémantique par valeur (style STL).
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
std::int64_t Int64
Type entier signé sur 64 bits.
Int32 Integer
Type représentant un entier.
ConstArrayView< Byte > ByteConstArrayView
Equivalent C d'un tableau à une dimension de caractères.
Definition UtilsTypes.h:474
std::int32_t Int32
Type entier signé sur 32 bits.