reproc (Proceso redirigido) es una biblioteca C/C++ multiplataforma que simplifica el inicio, la parada y la comunicación con programas externos. El caso de uso principal es ejecutar aplicaciones de línea de comandos directamente desde código C o C++ y recuperar su salida.
reproc consta de dos bibliotecas: reproc y reproc++. reproc es una biblioteca C99 que contiene el código real para trabajar con programas externos. reproc++ depende de reproc y adapta su API a una API idiomática de C++11. También agrega algunos extras que simplifican el trabajo con programas externos desde C++.
#include <reproc/run.h>
int main ( void )
{
const char * args [] = { "echo" , "Hello, world!" , NULL };
return reproc_run ( args , ( reproc_options ) { 0 });
}Si tiene alguna pregunta después de leer el archivo Léame y la documentación, puede generar un problema o hacer preguntas directamente en el canal de reproducción de Gitter.
Nota: La reproducción de compilación requiere CMake 3.12 o superior.
Hay varias formas de realizar reprocesamiento en su proyecto. Una forma es crear reprocesamiento como parte de su proyecto usando CMake. Para hacer esto, primero tenemos que introducir el código fuente de reproducción en el proyecto. Esto se puede hacer usando cualquiera de las siguientes opciones:
FetchContent para descargar la reproducción cuando ejecuta CMake. Consulte https://cliutils.gitlab.io/modern-cmake/chapters/projects/fetch.html para ver un ejemplo.Después de incluir el código fuente de reprocesamiento en su proyecto, se puede compilar desde el archivo raíz CMakeLists.txt de la siguiente manera:
add_subdirectory (< path -to-reproc>) # For example: add_subdirectory(external/reproc) Las opciones de CMake se pueden especificar antes de llamar add_subdirectory :
set (REPROC++ ON )
add_subdirectory (< path -to-reproc>)Nota: Si la opción ya se almacenó en caché en una ejecución anterior de CMake, deberá borrar la caché de CMake para aplicar el nuevo valor predeterminado.
Para obtener más información sobre cómo configurar la compilación de reprocesamiento, consulte Opciones de CMake.
También puede depender de una versión instalada de reproc. Puede compilar e instalar reproc usted mismo o instalarlo a través de un administrador de paquetes. reproc está disponible en los siguientes repositorios de paquetes:
Si usar un administrador de paquetes no es una opción, puede compilar e instalar reproc desde el código fuente (CMake 3.13+):
cmake -B build
cmake --build build
cmake --install build Habilite la opción REPROC_TEST y cree el objetivo test para ejecutar las pruebas (CMake 3.13+):
cmake -B build -DREPROC_TEST=ON
cmake --build build
cmake --build build --target testDespués de instalar reproc, su sistema de compilación tendrá que encontrarlo. reproc proporciona archivos de configuración de CMake y archivos pkg-config para simplificar la búsqueda de una instalación de reproces usando CMake y pkg-config respectivamente. Tenga en cuenta que reproc y reproc++ son bibliotecas separadas y, como resultado, también tienen archivos de configuración separados. Asegúrate de buscar el que deseas utilizar.
Para encontrar una versión instalada de reprocesamiento usando CMake:
find_package (reproc) # Find reproc.
find_package (reproc++) # Find reproc++.Después de compilar reproc como parte de su proyecto o encontrar una versión instalada de reproc, puede vincularlo desde su archivo CMakeLists.txt de la siguiente manera:
target_link_libraries (myapp reproc) # Link against reproc.
target_link_libraries (myapp reproc++) # Link against reproc++.Desde Meson 0.53.2 en adelante, la reproducción se puede incluir como un subproyecto CMake en los scripts de compilación de Meson. Consulte https://mesonbuild.com/CMake-module.html para obtener más información.
De forma predeterminada, reproc depende de pthreads en sistemas POSIX ( -pthread ) y de Winsock 2.2 en sistemas Windows ( -lws2_32 ). CMake y pkg-config manejan estas dependencias automáticamente.
La compilación de reproc se puede configurar usando las siguientes opciones de CMake:
REPROC++ : compilar reproc++ (predeterminado: ${REPROC_DEVELOP} )
REPROC_TEST : pruebas de compilación (predeterminado: ${REPROC_DEVELOP} )
Ejecute las pruebas ejecutando el binario test que se puede encontrar en el directorio de compilación después de compilar la reproducción.
REPROC_EXAMPLES : ejemplos de compilación (predeterminado: ${REPROC_DEVELOP} )
Los archivos binarios resultantes se ubicarán en la carpeta de ejemplos de cada subdirectorio del proyecto en el directorio de compilación después de compilar la reproducción.
REPROC_OBJECT_LIBRARIES : crea bibliotecas de objetos CMake (predeterminado: ${REPROC_DEVELOP} )
Esto es útil para incluir directamente la reproducción en otra biblioteca. Al crear reproc como una biblioteca estática o compartida, debe instalarse junto con la biblioteca consumidora, lo que dificulta la distribución de la biblioteca consumidora. Cuando se utilizan bibliotecas de objetos, los archivos de objetos de reproces se incluyen directamente en la biblioteca consumidora y no es necesaria ninguna instalación adicional.
Nota: las bibliotecas de objetos de Reproc solo se vincularán correctamente desde CMake 3.14 en adelante.
Nota: Esta opción anula BUILD_SHARED_LIBS .
REPROC_INSTALL : genera reglas de instalación (valor predeterminado: ON a menos que REPROC_OBJECT_LIBRARIES esté habilitado)
REPROC_INSTALL_CMAKECONFIGDIR : directorio de instalación de archivos de configuración de CMake (predeterminado: ${CMAKE_INSTALL_LIBDIR}/cmake )
REPROC_INSTALL_PKGCONFIG : instalar archivos pkg-config (predeterminado: ON )
REPROC_INSTALL_PKGCONFIGDIR : directorio de instalación de archivos pkg-config (predeterminado: ${CMAKE_INSTALL_LIBDIR}/pkgconfig )
REPROC_MULTITHREADED : use pthread_sigmask y vincule con la biblioteca de subprocesos del sistema (predeterminado: ON )
REPROC_DEVELOP : configura los valores predeterminados de la opción para el desarrollo (predeterminado: OFF a menos que la variable de entorno REPROC_DEVELOP esté configurada)REPROC_SANITIZERS : Compilación con desinfectantes (predeterminado: ${REPROC_DEVELOP} )REPROC_TIDY : ejecuta clang-tidy al compilar (predeterminado: ${REPROC_DEVELOP} )REPROC_WARNINGS : habilita las advertencias del compilador (predeterminado: ${REPROC_DEVELOP} )REPROC_WARNINGS_AS_ERRORS : agregue -Werror o equivalente a los indicadores de compilación y clang-tidy (predeterminado: OFF ) Cada función y clase está ampliamente documentada en su archivo de encabezado. Se pueden encontrar ejemplos en el subdirectorio de ejemplos de reproc y reproc++.
En caso de falla, la mayoría de las funciones en la API de reproducción devuelven un código de error de estilo errno negativo (POSIX) o GetLastError (Windows). Para errores procesables, reproc proporciona constantes ( REPROC_ETIMEDOUT , REPROC_EPIPE , ...) que se pueden usar para comparar el error sin tener que escribir código específico de la plataforma. Para obtener una representación de cadena de un error, páselo a reproc_strerror .
La API de reproc++ se integra con el mecanismo de códigos de error de la biblioteca estándar de C++ ( std::error_code y std::error_condition ). La mayoría de los métodos en la API de reproc++ devuelven valores std::error_code que contienen el error real del sistema que ocurrió. Puede realizar pruebas con estos códigos de error utilizando valores de la enumeración std::errc .
Consulte los ejemplos para obtener más información sobre cómo manejar errores al usar reprocesamiento.
Nota:
Tanto la API de reproc como la de reproc++ toman argumentos options que pueden definir una o más acciones stop , como terminate o kill . Por ese motivo, si el proceso secundario se finaliza o elimina mediante una señal en POSIX, el código de error no reflejará un error.
Depende del proyecto posterior interpretar los códigos de estado que reflejan comportamientos inesperados junto con los códigos de error (consulte este ejemplo).
No llame a la misma operación en el mismo proceso hijo desde más de un subproceso al mismo tiempo. Por ejemplo: leer y escribir en un proceso hijo desde diferentes subprocesos está bien, pero esperar en el mismo proceso hijo desde dos subprocesos diferentes al mismo tiempo generará problemas.
(POSIX) Se recomienda encarecidamente no llamar waitpid en pids de procesos iniciados por reprocesamiento.
reproc usa waitpid para esperar hasta que un proceso haya salido. Desafortunadamente, no se puede llamar waitpid dos veces en el mismo proceso. Esto significa que reproc_wait no funcionará correctamente si ya se ha llamado waitpid en un proceso hijo de antemano fuera de reproc.
Se recomienda encarecidamente asegurarse de que cada proceso hijo realmente salga usando reproc_wait o reproc_stop .
En POSIX, un proceso hijo que ha salido es un proceso zombie hasta que el proceso padre lo espera usando waitpid . Un proceso zombie consume recursos y puede verse como una fuga de recursos, por lo que es importante asegurarse de que todos los procesos finalicen correctamente en el momento oportuno.
Se recomienda encarecidamente intentar finalizar un proceso hijo esperando a que salga o llamando reproc_terminate antes de recurrir a reproc_kill .
Cuando se usa reproc_kill el proceso hijo no tiene la oportunidad de realizar la limpieza, lo que podría provocar la fuga de recursos. La principal de estas filtraciones es que el proceso hijo no podrá detener sus propios procesos hijo. Intente siempre permitir que un proceso hijo salga normalmente llamando reproc_terminate antes de llamar reproc_kill . reproc_stop es una función auxiliar útil que se puede utilizar para realizar múltiples acciones de detención seguidas con tiempos de espera intermedios.
(POSIX) Se recomienda encarecidamente ignorar la señal SIGPIPE en el proceso principal.
En POSIX, escribir en una tubería estándar cerrada de un proceso hijo finalizará el proceso padre con la señal SIGPIPE de forma predeterminada. Para evitar esto, la señal SIGPIPE debe ignorarse en el proceso principal. Si se ignora la señal SIGPIPE , reproc_write devolverá REPROC_EPIPE como se esperaba al escribir en una tubería estándar cerrada.
Si bien reproc_terminate permite que el proceso hijo realice la limpieza, depende del proceso hijo limpiarlo correctamente después de sí mismo. reproc solo envía una señal de terminación al proceso hijo. El propio proceso hijo es responsable de limpiar sus propios procesos hijo y otros recursos.
(Windows) No se garantiza que reproc_kill elimine un proceso secundario inmediatamente en Windows. Para obtener más información, lea la sección Comentarios en la documentación de la función TerminateProcess de Windows que utiliza reproc para finalizar procesos secundarios en Windows.
Los procesos secundarios generados mediante reproducción heredan un único identificador de archivo adicional que se utiliza para esperar a que salga el proceso secundario. Si el proceso hijo cierra este identificador de archivo manualmente, reproc detectará erróneamente que el proceso hijo ha salido. Si este identificador es heredado por otros procesos que sobreviven al proceso hijo, reproc detectará que el proceso hijo todavía se está ejecutando incluso si ha salido. Si se escriben datos en este identificador, el reprocesamiento también detectará erróneamente que el proceso hijo ha salido.
(Windows) No es posible detectar si un proceso secundario cierra su flujo stdout o stderr antes de salir. El proceso principal solo será notificado de que el flujo de salida de un proceso secundario se cierra una vez que ese proceso secundario salga.
(Windows) el reprocesamiento supone que Windows crea sockets que se pueden utilizar como objetos del sistema de archivos. Más específicamente, los sockets predeterminados devueltos por WSASocket deben tener configurado el indicador XP1_IFS_HANDLES . Es posible que este no sea el caso si hay proveedores LSP externos instalados en una máquina con Windows. Si este es el caso, recomendamos eliminar el software que proporciona proveedores de servicios adicionales, ya que están obsoletos y ya no deberían usarse (consulte https://docs.microsoft.com/en-us/windows/win32/winsock/ categorización-de-proveedores-y-aplicaciones-de-servicios-en-capas).