reproc (Redirected Process) — это кроссплатформенная библиотека C/C++, которая упрощает запуск, остановку и взаимодействие с внешними программами. Основной вариант использования — выполнение приложений командной строки непосредственно из кода C или C++ и получение их выходных данных.
reproc состоит из двух библиотек: reproc и reproc++. reproc — это библиотека C99, содержащая реальный код для работы с внешними программами. reproc++ зависит от reproc и адаптирует свой API к идиоматическому API C++11. Также добавлено несколько дополнений, упрощающих работу с внешними программами на C++.
#include <reproc/run.h>
int main ( void )
{
const char * args [] = { "echo" , "Hello, world!" , NULL };
return reproc_run ( args , ( reproc_options ) { 0 });
}
Если после прочтения файла readme и документации у вас возникнут какие-либо вопросы, вы можете либо сообщить о проблеме, либо задать вопросы непосредственно в канале reproc gitter.
Примечание. Для создания копии требуется CMake 3.12 или более поздней версии.
Есть несколько способов включить воспроизведение в ваш проект. Один из способов — создать репликацию как часть вашего проекта с помощью CMake. Для этого нам сначала нужно добавить в проект исходный код репликации. Это можно сделать, используя любой из следующих вариантов:
FetchContent
для загрузки репликации при запуске CMake. Пример см. на https://cliutils.gitlab.io/modern-cmake/chapters/projects/fetch.html.После включения исходного кода репликации в ваш проект его можно собрать из корневого файла CMakeLists.txt следующим образом:
add_subdirectory (< path -to-reproc>) # For example: add_subdirectory(external/reproc)
Параметры CMake можно указать перед вызовом add_subdirectory
:
set (REPROC++ ON )
add_subdirectory (< path -to-reproc>)
Примечание. Если этот параметр уже был кэширован при предыдущем запуске CMake, вам придется очистить кеш CMake, чтобы применить новое значение по умолчанию.
Дополнительные сведения о настройке сборки репликации см. в разделе Параметры CMake.
Вы также можете зависеть от установленной версии reproc. Вы можете либо собрать и установить реплику самостоятельно, либо установить реплику через менеджер пакетов. reproc доступен в следующих репозиториях пакетов:
Если использование менеджера пакетов невозможно, вы можете собрать и установить копию из исходного кода (CMake 3.13+):
cmake -B build
cmake --build build
cmake --install build
Включите опцию REPROC_TEST
и создайте test
цель для запуска тестов (CMake 3.13+):
cmake -B build -DREPROC_TEST=ON
cmake --build build
cmake --build build --target test
После установки reproc ваша система сборки должна будет его найти. reproc предоставляет как файлы конфигурации CMake, так и файлы pkg-config, чтобы упростить поиск установки репликации с помощью CMake и pkg-config соответственно. Обратите внимание, что reproc и reproc++ — это отдельные библиотеки и, как следствие, также имеют отдельные файлы конфигурации. Обязательно найдите тот, который вы хотите использовать.
Чтобы найти установленную версию репликации с помощью CMake:
find_package (reproc) # Find reproc.
find_package (reproc++) # Find reproc++.
После создания реплики как части вашего проекта или обнаружения установленной версии реплики вы можете связать ее с файлом CMakeLists.txt следующим образом:
target_link_libraries (myapp reproc) # Link against reproc.
target_link_libraries (myapp reproc++) # Link against reproc++.
Начиная с Meson 0.53.2, репликация может быть включена как подпроект CMake в сценарии сборки Meson. Дополнительную информацию см. на https://mesonbuild.com/CMake-module.html.
По умолчанию reproc зависит от pthreads в системах POSIX ( -pthread
) и от Winsock 2.2 в системах Windows ( -lws2_32
). CMake и pkg-config автоматически обрабатывают эти зависимости.
Сборку reproc можно настроить с помощью следующих параметров CMake:
REPROC++
: построить reproc++ (по умолчанию: ${REPROC_DEVELOP}
).
REPROC_TEST
: тесты сборки (по умолчанию: ${REPROC_DEVELOP}
).
Запустите тесты, запустив test
двоичный файл, который можно найти в каталоге сборки после сборки копии.
REPROC_EXAMPLES
: примеры сборки (по умолчанию: ${REPROC_DEVELOP}
).
Полученные двоичные файлы будут расположены в папке примеров каждого подкаталога проекта в каталоге сборки после сборки копии.
REPROC_OBJECT_LIBRARIES
: сборка библиотек объектов CMake (по умолчанию: ${REPROC_DEVELOP}
).
Это полезно для прямого включения воспроизведения в другую библиотеку. При создании репликации в виде статической или общей библиотеки ее необходимо устанавливать рядом с потребляющей библиотекой, что усложняет распространение потребляющей библиотеки. При использовании объектных библиотек объектные файлы реплик включаются непосредственно в потребляющую библиотеку, и дополнительная установка не требуется.
Примечание. Библиотеки объектов репликации будут корректно компоноваться только начиная с CMake 3.14.
Примечание. Этот параметр переопределяет BUILD_SHARED_LIBS
.
REPROC_INSTALL
: создание правил установки (по умолчанию: ON
, если REPROC_OBJECT_LIBRARIES
не включен).
REPROC_INSTALL_CMAKECONFIGDIR
: каталог установки файлов конфигурации CMake (по умолчанию: ${CMAKE_INSTALL_LIBDIR}/cmake
).
REPROC_INSTALL_PKGCONFIG
: установить файлы pkg-config (по умолчанию: ON
).
REPROC_INSTALL_PKGCONFIGDIR
: каталог установки файлов pkg-config (по умолчанию: ${CMAKE_INSTALL_LIBDIR}/pkgconfig
).
REPROC_MULTITHREADED
: используйте pthread_sigmask
и свяжите его с библиотекой потоков системы (по умолчанию: ON
).
REPROC_DEVELOP
: настройка значений параметров по умолчанию для разработки (по умолчанию: OFF
если не установлена переменная среды REPROC_DEVELOP
).REPROC_SANITIZERS
: сборка с использованием дезинфицирующих средств (по умолчанию: ${REPROC_DEVELOP}
).REPROC_TIDY
: запускать clang-tidy при сборке (по умолчанию: ${REPROC_DEVELOP}
).REPROC_WARNINGS
: включить предупреждения компилятора (по умолчанию: ${REPROC_DEVELOP}
).REPROC_WARNINGS_AS_ERRORS
: добавьте -Werror или эквивалент к флагам компиляции и clang-tidy (по умолчанию: OFF
). Каждая функция и класс подробно документированы в заголовочном файле. Примеры можно найти в подкаталоге примеров файлов reproc и reproc++.
В случае сбоя большинство функций в API репликации возвращают отрицательный код ошибки errno
(POSIX) или GetLastError
(Windows). Для ошибок, требующих действий, reproc предоставляет константы ( REPROC_ETIMEDOUT
, REPROC_EPIPE
, ...), которые можно использовать для сопоставления с ошибкой без необходимости писать код, специфичный для платформы. Чтобы получить строковое представление ошибки, передайте его в reproc_strerror
.
API reproc++ интегрируется с механизмом кодов ошибок стандартной библиотеки C++ ( std::error_code
и std::error_condition
). Большинство методов в API reproc++ возвращают значения std::error_code
, которые содержат фактическую произошедшую системную ошибку. Вы можете проверить эти коды ошибок, используя значения из перечисления std::errc
.
См. примеры для получения дополнительной информации о том, как обрабатывать ошибки при использовании воспроизведения.
Примечание:
API-интерфейсы reproc и reproc++ принимают аргумент options
, который может определять одно или несколько действий stop
, таких как terminate
или kill
. По этой причине, если дочерний процесс завершается или уничтожается с использованием сигнала POSIX, код ошибки не будет отражать ошибку.
Следующий проект должен интерпретировать коды состояния, отражающие неожиданное поведение, наряду с кодами ошибок (см. этот пример).
Не вызывайте одну и ту же операцию для одного и того же дочернего процесса из более чем одного потока одновременно. Например: чтение и запись в дочерний процесс из разных потоков — это нормально, но ожидание одного и того же дочернего процесса из двух разных потоков одновременно приведет к проблемам.
(POSIX) Настоятельно рекомендуется не вызывать waitpid
для pid процессов, запущенных с помощью reproc.
reproc использует waitpid
для ожидания завершения процесса. К сожалению, waitpid
не может быть вызван дважды в одном и том же процессе. Это означает, что reproc_wait
не будет работать правильно, если waitpid
уже был заранее вызван для дочернего процесса вне reproc.
Настоятельно рекомендуется убедиться, что каждый дочерний процесс действительно завершается с помощью reproc_wait
или reproc_stop
.
В POSIX завершившийся дочерний процесс является процессом-зомби до тех пор, пока родительский процесс не будет ждать его с помощью waitpid
. Процесс-зомби потребляет ресурсы и может рассматриваться как утечка ресурсов, поэтому важно убедиться, что все процессы завершаются правильно и своевременно.
Настоятельно рекомендуется попытаться завершить дочерний процесс, дождавшись его завершения или вызвав reproc_terminate
прежде чем прибегать к reproc_kill
.
При использовании reproc_kill
дочерний процесс не получает возможности выполнить очистку, что может привести к утечке ресурсов. Главной среди этих утечек является то, что дочерний процесс не сможет остановить свои собственные дочерние процессы. Всегда старайтесь позволить дочернему процессу завершиться нормально, вызывая reproc_terminate
перед вызовом reproc_kill
. reproc_stop
— это удобная вспомогательная функция, которую можно использовать для выполнения нескольких действий остановки подряд с промежутками времени ожидания.
(POSIX) Настоятельно рекомендуется игнорировать сигнал SIGPIPE
в родительском процессе.
В POSIX запись в закрытый канал stdin дочернего процесса по умолчанию завершает родительский процесс с помощью сигнала SIGPIPE
. Чтобы избежать этого, сигнал SIGPIPE
должен игнорироваться в родительском процессе. Если сигнал SIGPIPE
игнорируется, reproc_write
вернет REPROC_EPIPE
, как и ожидалось, при записи в закрытый канал stdin.
Хотя reproc_terminate
позволяет дочернему процессу выполнять очистку, правильность очистки после себя зависит от дочернего процесса. reproc только отправляет сигнал завершения дочернему процессу. Сам дочерний процесс отвечает за очистку своих дочерних процессов и других ресурсов.
(Windows) reproc_kill
не гарантирует немедленное завершение дочернего процесса в Windows. Для получения дополнительной информации прочтите раздел «Примечания» в документации по функции Windows TerminateProcess
, которую функция reproc использует для завершения дочерних процессов в Windows.
Дочерние процессы, порожденные посредством reproc, наследуют один дополнительный дескриптор файла, который используется для ожидания завершения дочернего процесса. Если дочерний процесс закроет этот дескриптор файла вручную, функция репликации ошибочно обнаружит, что дочерний процесс завершился. Если этот дескриптор в дальнейшем унаследован другими процессами, пережившими дочерний процесс, функция reproc обнаружит, что дочерний процесс все еще работает, даже если он завершился. Если в этот дескриптор записываются данные, функция reproc также ошибочно обнаружит выход дочернего процесса.
(Windows) Невозможно определить, закрывает ли дочерний процесс свой поток stdout или stderr перед выходом. Родительский процесс будет уведомлен о закрытии выходного потока дочернего процесса только после завершения дочернего процесса.
При воспроизведении (Windows) предполагается, что Windows создает сокеты, которые можно использовать в качестве объектов файловой системы. Точнее, сокеты по умолчанию, возвращаемые WSASocket
должны иметь установленный флаг XP1_IFS_HANDLES
. Это может быть не так, если на компьютере под управлением Windows установлены внешние поставщики LSP. В этом случае мы рекомендуем удалить программное обеспечение, предоставляющее дополнительных поставщиков услуг, поскольку они устарели и больше не должны использоваться (см. https://docs.microsoft.com/en-us/windows/win32/winsock/). категоризация многоуровневых поставщиков услуг и приложений).