reproc (Redirected Process) est une bibliothèque C/C++ multiplateforme qui simplifie le démarrage, l'arrêt et la communication avec des programmes externes. Le cas d'utilisation principal consiste à exécuter des applications en ligne de commande directement à partir du code C ou C++ et à récupérer leur sortie.
reproc se compose de deux bibliothèques : reproc et reproc++. reproc est une bibliothèque C99 qui contient le code réel permettant de travailler avec des programmes externes. reproc++ dépend de reproc et adapte son API à une API C++11 idiomatique. Il ajoute également quelques extras qui simplifient le travail avec des programmes externes de C++.
#include <reproc/run.h>
int main ( void )
{
const char * args [] = { "echo" , "Hello, world!" , NULL };
return reproc_run ( args , ( reproc_options ) { 0 });
}
Si vous avez des questions après avoir lu le fichier readme et la documentation, vous pouvez soit créer un problème, soit poser des questions directement dans le canal reproc gitter.
Remarque : La création de reproc nécessite CMake 3.12 ou supérieur.
Il existe plusieurs façons d'intégrer la reproduction dans votre projet. Une solution consiste à créer une reproduction dans le cadre de votre projet à l'aide de CMake. Pour ce faire, nous devons d'abord insérer le code source de la repro dans le projet. Cela peut être fait en utilisant l'une des options suivantes :
FetchContent
pour télécharger la reproduction lors de l'exécution de CMake. Voir https://cliutils.gitlab.io/modern-cmake/chapters/projects/fetch.html pour un exemple.Après avoir inclus le code source de reproc dans votre projet, il peut être construit à partir du fichier racine CMakeLists.txt comme suit :
add_subdirectory (< path -to-reproc>) # For example: add_subdirectory(external/reproc)
Les options CMake peuvent être spécifiées avant d'appeler add_subdirectory
:
set (REPROC++ ON )
add_subdirectory (< path -to-reproc>)
Remarque : Si l'option a déjà été mise en cache lors d'une exécution précédente de CMake, vous devrez vider le cache de CMake pour appliquer la nouvelle valeur par défaut.
Pour plus d'informations sur la configuration de la build de reproc, consultez les options CMake.
Vous pouvez également compter sur une version installée de reproc. Vous pouvez soit créer et installer reproc vous-même, soit installer reproc via un gestionnaire de packages. reproc est disponible dans les référentiels de packages suivants :
Si l'utilisation d'un gestionnaire de packages n'est pas une option, vous pouvez créer et installer reproc à partir des sources (CMake 3.13+) :
cmake -B build
cmake --build build
cmake --install build
Activez l'option REPROC_TEST
et créez la cible test
pour exécuter les tests (CMake 3.13+) :
cmake -B build -DREPROC_TEST=ON
cmake --build build
cmake --build build --target test
Après avoir installé reproc, votre système de build devra le trouver. reproc fournit à la fois des fichiers de configuration CMake et des fichiers pkg-config pour simplifier la recherche d'une installation de reproc en utilisant respectivement CMake et pkg-config. Notez que reproc et reproc++ sont des bibliothèques distinctes et ont donc également des fichiers de configuration distincts. Assurez-vous de rechercher celui que vous souhaitez utiliser.
Pour rechercher une version installée de reproc à l'aide de CMake :
find_package (reproc) # Find reproc.
find_package (reproc++) # Find reproc++.
Après avoir créé reproc dans le cadre de votre projet ou trouvé une version installée de reproc, vous pouvez créer un lien vers celle-ci à partir de votre fichier CMakeLists.txt comme suit :
target_link_libraries (myapp reproc) # Link against reproc.
target_link_libraries (myapp reproc++) # Link against reproc++.
À partir de Meson 0.53.2, reproc peut être inclus en tant que sous-projet CMake dans les scripts de construction Meson. Voir https://mesonbuild.com/CMake-module.html pour plus d'informations.
Par défaut, reproc a une dépendance sur pthreads sur les systèmes POSIX ( -pthread
) et une dépendance sur Winsock 2.2 sur les systèmes Windows ( -lws2_32
). CMake et pkg-config gèrent automatiquement ces dépendances.
La build de reproc peut être configurée à l'aide des options CMake suivantes :
REPROC++
: Build reproc++ (par défaut : ${REPROC_DEVELOP}
)
REPROC_TEST
: Build tests (par défaut : ${REPROC_DEVELOP}
)
Exécutez les tests en exécutant le binaire test
qui se trouve dans le répertoire de construction après la création de reproc.
REPROC_EXAMPLES
: Exemples de build (par défaut : ${REPROC_DEVELOP}
)
Les binaires résultants seront situés dans le dossier d'exemples de chaque sous-répertoire de projet dans le répertoire de construction après la construction de reproc.
REPROC_OBJECT_LIBRARIES
: Créer des bibliothèques d'objets CMake (par défaut : ${REPROC_DEVELOP}
)
Ceci est utile pour inclure directement reproc dans une autre bibliothèque. Lors de la création de reproc en tant que bibliothèque statique ou partagée, elle doit être installée à côté de la bibliothèque consommatrice, ce qui rend la distribution de la bibliothèque consommatrice plus difficile. Lors de l'utilisation de bibliothèques d'objets, les fichiers objets de reproc sont inclus directement dans la bibliothèque consommatrice et aucune installation supplémentaire n'est nécessaire.
Remarque : les bibliothèques d'objets de reproc ne seront liées correctement qu'à partir de CMake 3.14.
Remarque : Cette option remplace BUILD_SHARED_LIBS
.
REPROC_INSTALL
: Générer des règles d'installation (par défaut : ON
sauf si REPROC_OBJECT_LIBRARIES
est activé)
REPROC_INSTALL_CMAKECONFIGDIR
: répertoire d'installation des fichiers de configuration CMake (par défaut : ${CMAKE_INSTALL_LIBDIR}/cmake
)
REPROC_INSTALL_PKGCONFIG
: Installer les fichiers pkg-config (par défaut : ON
)
REPROC_INSTALL_PKGCONFIGDIR
: répertoire d'installation des fichiers pkg-config (par défaut : ${CMAKE_INSTALL_LIBDIR}/pkgconfig
)
REPROC_MULTITHREADED
: utilisez pthread_sigmask
et établissez un lien avec la bibliothèque de threads du système (par défaut : ON
)
REPROC_DEVELOP
: Configurer les valeurs par défaut des options pour le développement (par défaut : OFF
sauf si la variable d'environnement REPROC_DEVELOP
est définie)REPROC_SANITIZERS
: Construire avec des désinfectants (par défaut : ${REPROC_DEVELOP}
)REPROC_TIDY
: Exécutez clang-tidy lors de la construction (par défaut : ${REPROC_DEVELOP}
)REPROC_WARNINGS
: Activer les avertissements du compilateur (par défaut : ${REPROC_DEVELOP}
)REPROC_WARNINGS_AS_ERRORS
: Ajoutez -Werror ou équivalent aux indicateurs de compilation et clang-tidy (par défaut : OFF
) Chaque fonction et classe est largement documentée dans son fichier d'en-tête. Des exemples peuvent être trouvés dans le sous-répertoire examples de reproc et reproc++.
En cas d'échec, la plupart des fonctions de l'API de reproc renvoient un code d'erreur de style errno
négatif (POSIX) ou GetLastError
(Windows). Pour les erreurs exploitables, reproc fournit des constantes ( REPROC_ETIMEDOUT
, REPROC_EPIPE
, ...) qui peuvent être utilisées pour comparer l'erreur sans avoir à écrire de code spécifique à la plate-forme. Pour obtenir une représentation sous forme de chaîne d'une erreur, transmettez-la à reproc_strerror
.
L'API de reproc++ s'intègre au mécanisme de codes d'erreur de la bibliothèque standard C++ ( std::error_code
et std::error_condition
). La plupart des méthodes de l'API de reproc++ renvoient des valeurs std::error_code
qui contiennent l'erreur système réelle qui s'est produite. Vous pouvez tester ces codes d'erreur en utilisant les valeurs de l'énumération std::errc
.
Consultez les exemples pour plus d’informations sur la façon de gérer les erreurs lors de l’utilisation de reproc.
Note:
Les API reproc et reproc++ acceptent un argument options
qui peut définir une ou plusieurs actions stop
telles que terminate
ou kill
. Pour cette raison, si le processus enfant est terminé ou tué à l'aide d'un signal sur POSIX, le code d'erreur ne reflétera pas une erreur.
C'est au projet en aval d' interpréter les codes d'état reflétant des comportements inattendus aux côtés des codes d'erreur (voir cet exemple).
N'appelez pas la même opération sur le même processus enfant à partir de plusieurs threads en même temps. Par exemple : lire et écrire sur un processus enfant à partir de différents threads est acceptable, mais attendre simultanément le même processus enfant à partir de deux threads différents entraînera des problèmes.
(POSIX) Il est fortement recommandé de ne pas appeler waitpid
sur les pids des processus démarrés par reproc.
reproc utilise waitpid
pour attendre la fin d'un processus. Malheureusement, waitpid
ne peut pas être appelé deux fois sur le même processus. Cela signifie que reproc_wait
ne fonctionnera pas correctement si waitpid
a déjà été appelé sur un processus enfant au préalable en dehors de reproc.
Il est fortement recommandé de s'assurer que chaque processus enfant se termine réellement en utilisant reproc_wait
ou reproc_stop
.
Sous POSIX, un processus enfant qui s'est terminé est un processus zombie jusqu'à ce que le processus parent l'attende en utilisant waitpid
. Un processus zombie consomme des ressources et peut être considéré comme une fuite de ressources. Il est donc important de s'assurer que tous les processus se terminent correctement et en temps opportun.
Il est fortement recommandé d'essayer de terminer un processus enfant en attendant qu'il se termine ou en appelant reproc_terminate
avant de recourir à reproc_kill
.
Lors de l'utilisation reproc_kill
le processus enfant n'a pas la possibilité d'effectuer un nettoyage, ce qui pourrait entraîner une fuite de ressources. La principale de ces fuites est que le processus enfant ne sera pas en mesure d'arrêter ses propres processus enfants. Essayez toujours de laisser un processus enfant se terminer normalement en appelant reproc_terminate
avant d'appeler reproc_kill
. reproc_stop
est une fonction d'assistance pratique qui peut être utilisée pour effectuer plusieurs actions d'arrêt d'affilée avec des délais d'attente entre les deux.
(POSIX) Il est fortement recommandé d'ignorer le signal SIGPIPE
dans le processus parent.
Sous POSIX, l'écriture dans un tube stdin fermé d'un processus enfant mettra fin au processus parent avec le signal SIGPIPE
par défaut. Pour éviter cela, le signal SIGPIPE
doit être ignoré dans le processus parent. Si le signal SIGPIPE
est ignoré, reproc_write
renverra REPROC_EPIPE
comme prévu lors de l'écriture dans un tube stdin fermé.
Bien que reproc_terminate
permette au processus enfant d'effectuer un nettoyage, il appartient au processus enfant de nettoyer correctement après lui-même. reproc envoie uniquement un signal de fin au processus enfant. Le processus enfant lui-même est responsable du nettoyage de ses propres processus enfants et d'autres ressources.
(Windows) il n'est pas garanti que reproc_kill
tue immédiatement un processus enfant sous Windows. Pour plus d'informations, lisez la section Remarques dans la documentation de la fonction Windows TerminateProcess
que reproc utilise pour tuer les processus enfants sous Windows.
Les processus enfants générés via reproc héritent d'un seul descripteur de fichier supplémentaire qui est utilisé pour attendre la fin du processus enfant. Si le processus enfant ferme manuellement ce descripteur de fichier, la procédure détectera à tort que le processus enfant s'est terminé. Si ce handle est hérité par d'autres processus qui survivent au processus enfant, reproc détectera que le processus enfant est toujours en cours d'exécution même s'il s'est arrêté. Si des données sont écrites sur ce handle, reproc détectera également à tort que le processus enfant s'est terminé.
(Windows) Il n'est pas possible de détecter si un processus enfant ferme son flux stdout ou stderr avant de quitter. Le processus parent ne sera informé qu'un flux de sortie d'un processus enfant est fermé une fois ce processus enfant terminé.
(Windows) la procédure suppose que Windows crée des sockets utilisables en tant qu'objets du système de fichiers. Plus précisément, les sockets par défaut renvoyées par WSASocket
doivent avoir l'indicateur XP1_IFS_HANDLES
défini. Cela peut ne pas être le cas si des fournisseurs LSP externes sont installés sur une machine Windows. Si tel est le cas, nous vous recommandons de supprimer le logiciel qui fournit les fournisseurs de services supplémentaires car ils sont obsolètes et ne doivent plus être utilisés (voir https://docs.microsoft.com/en-us/windows/win32/winsock/ catégorisation des fournisseurs de services et des applications à plusieurs niveaux).