Arcane  v3.14.10.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-2022 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-2016 */
9/* */
10/* Gestion des processus. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/utils/ArcanePrecomp.h"
15
16#include "arcane/utils/NotImplementedException.h"
17#include "arcane/utils/OStringStream.h"
18#include "arcane/utils/Process.h"
19
20/*
21 * NOTE: pour l'instant cette classe n'est implémentée que pour Linux
22 * (elle devrait cependant fonctionner avec les autres Unix).
23 */
24
25#ifdef ARCANE_OS_LINUX
26#include <unistd.h>
27#include <sys/wait.h>
28#include <fcntl.h>
29#endif
30
31/*---------------------------------------------------------------------------*/
32/*---------------------------------------------------------------------------*/
33
34ARCANE_BEGIN_NAMESPACE
35
36/*---------------------------------------------------------------------------*/
37/*---------------------------------------------------------------------------*/
38
39/*---------------------------------------------------------------------------*/
40/*---------------------------------------------------------------------------*/
41
43execute(ProcessExecArgs& args)
44{
45#ifdef ARCANE_OS_LINUX
46 args.m_output_bytes.clear();
48
49 // Créé deux pipes pour rediriger les entrées et les sorties du
50 // processus qu'on va lancer.
51 int pipefd_out[2];
52 int pipefd_in[2];
54 if (r0!=0)
55 return ProcessExecArgs::ExecStatus::CanNotCreatePipe;
57 if (r0!=0)
58 return ProcessExecArgs::ExecStatus::CanNotCreatePipe;
59 pid_t cpid = ::fork();
60 if (cpid<0)
61 return ProcessExecArgs::ExecStatus::CanNotFork;
62
63 ProcessExecArgs::ExecStatus exec_status = ProcessExecArgs::ExecStatus::OK;
64 if (cpid==0){
65 // Je suis le processus fils.
66
67 // TODO: vérifier les erreurs des close() et dup2().
68
69 // Indique que pipefd_out[1] correspond à mon STDOUT
70 ::close(STDOUT_FILENO);
71 ::close(pipefd_out[0]);
72 ::dup2(pipefd_out[1],STDOUT_FILENO);
73
74 // Indique que pipefd_in[0] correspond à mon STDIN
75 ::close(STDIN_FILENO);
76 ::close(pipefd_in[1]);
77 ::dup2(pipefd_in[0],STDIN_FILENO);
78
79 const char* cmd_name = args.command().localstr();
80
81 StringConstArrayView arguments = args.arguments();
82 Integer nb_arg = arguments.size();
83 // Le tableau passé à execve() pour les arguments doit se terminer par NULL
84 // et commencer par le nom de l'exécutable
86 for( Integer i=0; i<nb_arg; ++i )
87 command_args[i+1] = arguments[i].localstr();
89 command_args[nb_arg+1] = nullptr;
90
91 const char *const newenviron[] = { NULL };
92 ::execve(cmd_name, (char* const*)command_args.data(), (char* const*)newenviron);
93 // L'appel à execve() ne retourne pas.
94
95 }
96 else{
97 ::close(pipefd_out[1]);
98 ::close(pipefd_in[0]);
99 // Ecrit sur le pipe d'entrée les octets de \a input_bytes
100 Int64 nb_wanted_write = input_bytes.size();
101 Int64 nb_written = ::write(pipefd_in[1],input_bytes.data(),nb_wanted_write);
103 std::cerr << "Error writing to pipe\n";
104 ::close(pipefd_in[1]);
105 const int BUF_SIZE=4096;
106 Byte buf[BUF_SIZE];
107 ssize_t r = 0;
108 // TODO: gérer les interruptions et recommencer si nécessaire
109 while ((r=::read(pipefd_out[0], buf, BUF_SIZE)) > 0){
110 args.m_output_bytes.addRange(ByteConstArrayView((Integer)r,buf));
111 //::write(STDOUT_FILENO, buf, r);
112 }
113 // Attend que le processus fils soit fini.
114 int status = 0;
115 ::waitpid(cpid,&status,0); /* Wait for child */
116 if (WIFEXITED(status)){
117 args.m_exit_code = WEXITSTATUS(status);
118 //printf("exited, status=%d\n", WEXITSTATUS(status));
119 }
120 else
121 exec_status = ProcessExecArgs::ExecStatus::AbnormalExit;
122
123 close(pipefd_out[0]);
124
125 // Ajoute un '\0' terminal au flux de sortie.
126 args.m_output_bytes.add('\0');
127 }
128 return exec_status;
129#else
130 throw NotImplementedException(A_FUNCINFO);
131#endif
132}
133
134/*---------------------------------------------------------------------------*/
135/*---------------------------------------------------------------------------*/
136
137ARCANE_END_NAMESPACE
138
139/*---------------------------------------------------------------------------*/
140/*---------------------------------------------------------------------------*/
Lecteur des fichiers de maillage via la bibliothèque LIMA.
Definition Lima.cc:120
String command() const
Commande à exécuter. Doit correspondre à un exécutable.
Definition Process.h:47
ByteConstArrayView inputBytes() const
Chaîne de caractère à envoyer sur l'entrée standard (STDIN) du processsus.
Definition Process.h:56
StringConstArrayView arguments() const
Liste des arguments.
Definition Process.h:51
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.
void clear()
Supprime les éléments du tableau.
Vue constante d'un tableau de type T.
constexpr Integer size() const noexcept
Nombre d'éléments du tableau.
Exception lorsqu'une fonction n'est pas implémentée.
const char * localstr() const
Retourne la conversion de l'instance dans l'encodage UTF-8.
Definition String.cc:227