reproc (Redirected Process) は、外部プログラムの起動、停止、通信を簡素化するクロスプラットフォームの C/C++ ライブラリです。主な使用例は、C または C++ コードからコマンド ライン アプリケーションを直接実行し、その出力を取得することです。
reproc は、reproc と reproc++ の 2 つのライブラリで構成されます。 reproc は、外部プログラムを操作するための実際のコードを含む C99 ライブラリです。 reproc++ は reproc に依存しており、その API を慣用的な C++11 API に適合させます。また、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 チャネルで直接質問することができます。
注: reproc のビルドには CMake 3.12 以降が必要です。
プロジェクトに reproc を組み込む方法は複数あります。 1 つの方法は、CMake を使用してプロジェクトの一部として reproc をビルドすることです。これを行うには、まず reproc ソース コードをプロジェクトに取り込む必要があります。これは、次のオプションのいずれかを使用して実行できます。
FetchContent
API を使用して、CMake の実行時に再現をダウンロードできます。例については、https://cliutils.gitlab.io/modern-cmake/chapters/projects/fetch.html を参照してください。reproc のソース コードをプロジェクトに含めた後、次のようにルートの 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 のキャッシュをクリアする必要があります。
Reproc のビルドの構成の詳細については、「CMake オプション」を参照してください。
インストールされている reproc のバージョンに依存することもできます。 reproc を自分でビルドしてインストールすることも、パッケージ マネージャーを介して reproc をインストールすることもできます。 reproc は次のパッケージ リポジトリで利用できます。
パッケージ マネージャーを使用できない場合は、ソース (CMake 3.13 以降) から reproc をビルドしてインストールできます。
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 と reproc++ は別個のライブラリであるため、別個の設定ファイルも存在することに注意してください。ぜひ使いたいものを探してみてください。
CMake を使用して reproc のインストールされているバージョンを見つけるには:
find_package (reproc) # Find reproc.
find_package (reproc++) # Find reproc++.
プロジェクトの一部として reproc をビルドするか、インストールされているバージョンの reproc を見つけたら、次のように CMakeLists.txt ファイル内からそのバージョンにリンクできます。
target_link_libraries (myapp reproc) # Link against reproc.
target_link_libraries (myapp reproc++) # Link against reproc++.
Meson 0.53.2 以降では、reproc を CMake サブプロジェクトとして Meson ビルド スクリプトに含めることができます。詳細については、https://mesonbuild.com/CMake-module.html を参照してください。
デフォルトでは、reproc は POSIX システムでは pthread に依存し ( -pthread
)、Windows システムでは Winsock 2.2 に依存します ( -lws2_32
)。 CMake と pkg-config は、これらの依存関係を自動的に処理します。
reproc のビルドは、次の CMake オプションを使用して構成できます。
REPROC++
: reproc++ をビルドします (デフォルト: ${REPROC_DEVELOP}
)
REPROC_TEST
: テストをビルドします (デフォルト: ${REPROC_DEVELOP}
)
reproc のビルド後にビルド ディレクトリにあるtest
バイナリを実行してテストを実行します。
REPROC_EXAMPLES
: ビルド例 (デフォルト: ${REPROC_DEVELOP}
)
結果のバイナリは、reproc のビルド後にビルド ディレクトリ内の各プロジェクト サブディレクトリのサンプル フォルダーに配置されます。
REPROC_OBJECT_LIBRARIES
: CMake オブジェクト ライブラリをビルドします (デフォルト: ${REPROC_DEVELOP}
)
これは、reproc を別のライブラリに直接組み込む場合に便利です。 reproc を静的ライブラリまたは共有ライブラリとして構築する場合、それを使用するライブラリと一緒にインストールする必要があるため、使用するライブラリの配布が難しくなります。オブジェクト ライブラリを使用する場合、reproc のオブジェクト ファイルは使用するライブラリに直接組み込まれるため、追加のインストールは必要ありません。
注: reproc のオブジェクト ライブラリは、CMake 3.14 以降でのみ正しくリンクされます。
注: このオプションはBUILD_SHARED_LIBS
をオーバーライドします。
REPROC_INSTALL
: インストール ルールを生成します (デフォルト: REPROC_OBJECT_LIBRARIES
が有効でない場合はON
)
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
: 開発用のオプションのデフォルト値を構成します ( REPROC_DEVELOP
環境変数が設定されていない限り、デフォルト: OFF
)REPROC_SANITIZERS
: サニタイザーを使用してビルドします (デフォルト: ${REPROC_DEVELOP}
)REPROC_TIDY
: ビルド時にclang-tidyを実行します(デフォルト: ${REPROC_DEVELOP}
)REPROC_WARNINGS
: コンパイラ警告を有効にします (デフォルト: ${REPROC_DEVELOP}
)REPROC_WARNINGS_AS_ERRORS
: -Werror またはコンパイル フラグと同等のものを追加し、clang-tidy (デフォルト: OFF
) 各関数とクラスはヘッダー ファイルに詳しく文書化されています。例は、reproc および reproc++ の example サブディレクトリにあります。
失敗すると、reproc の API のほとんどの関数は、負のerrno
(POSIX) またはGetLastError
(Windows) 形式のエラー コードを返します。対処可能なエラーの場合、reproc はプラットフォーム固有のコードを記述せずにエラーと照合するために使用できる定数 ( REPROC_ETIMEDOUT
、 REPROC_EPIPE
など) を提供します。エラーの文字列表現を取得するには、それをreproc_strerror
に渡します。
reproc++ の API は、C++ 標準ライブラリのエラー コード メカニズム ( std::error_code
およびstd::error_condition
) と統合されています。 reproc++ の API のほとんどのメソッドは、発生した実際のシステム エラーを含むstd::error_code
値を返します。 std::errc
列挙型の値を使用して、これらのエラー コードに対してテストできます。
reproc 使用時のエラーの処理方法の詳細については、例を参照してください。
注記:
reproc API と reproc++ API はどちらも、 terminate
やkill
などの 1 つ以上のstop
アクションを定義できるoptions
引数を受け取ります。そのため、POSIX 上のシグナルを使用して子プロセスが終了または強制終了されている場合、エラー コードにはエラーが反映されません。
エラー コードとともに予期せぬ動作を反映するステータス コードを解釈するかどうかは、下流プロジェクトの責任になります (この例を参照)。
同じ子プロセス上の同じ操作を複数のスレッドから同時に呼び出さないでください。たとえば、異なるスレッドから子プロセスへの読み取りと書き込みは問題ありませんが、2 つの異なるスレッドから同じ子プロセスを同時に待機すると問題が発生します。
(POSIX) reproc によって開始されたプロセスの pid に対してwaitpid
を呼び出さないことを強くお勧めします。
reproc は、 waitpid
使用してプロセスが終了するまで待機します。残念ながら、同じプロセス上でwaitpid
2 回呼び出すことはできません。これは、 waitpid
reproc の外部で事前に子プロセスですでに呼び出されている場合、 reproc_wait
正しく機能しないことを意味します。
reproc_wait
またはreproc_stop
を使用して、各子プロセスが実際に終了することを確認することを強くお勧めします。
POSIX では、親プロセスがwaitpid
使用して待機するまで、終了した子プロセスはゾンビ プロセスになります。ゾンビ プロセスはリソースを占有し、リソース リークとしてみなされるため、すべてのプロセスが適切なタイミングで正しく終了することが重要です。
reproc_kill
に頼る前に、子プロセスが終了するのを待つか、 reproc_terminate
を呼び出して子プロセスを終了することを強くお勧めします。
reproc_kill
使用すると、子プロセスはクリーンアップを実行する機会が得られないため、リソースがリークする可能性があります。これらのリークの主な原因は、子プロセスが自身の子プロセスを停止できないことです。 reproc_kill
呼び出す前にreproc_terminate
呼び出して、常に子プロセスを正常に終了させるようにしてください。 reproc_stop
は、タイムアウトを挟んで複数の停止アクションを連続して実行するために使用できる便利なヘルパー関数です。
(POSIX) 親プロセスではSIGPIPE
シグナルを無視することを強くお勧めします。
POSIX では、子プロセスの閉じられた stdin パイプに書き込むと、デフォルトでSIGPIPE
シグナルで親プロセスが終了します。これを回避するには、親プロセスでSIGPIPE
シグナルを無視する必要があります。 SIGPIPE
信号が無視された場合、 reproc_write
閉じられた stdin パイプに書き込むときに期待どおりREPROC_EPIPE
を返します。
reproc_terminate
では子プロセスがクリーンアップを実行できますが、子プロセス自身の後に正しくクリーンアップするかどうかは子プロセス次第です。 reproc は子プロセスに終了シグナルを送信するだけです。子プロセス自体は、自身の子プロセスとその他のリソースをクリーンアップする責任があります。
(Windows) Windows では、 reproc_kill
プロセスを即座に強制終了することは保証されていません。詳細については、Windows 上の子プロセスを強制終了するために reproc が使用する Windows TerminateProcess
関数のドキュメントの「備考」セクションを参照してください。
reproc によって生成された子プロセスは、子プロセスが終了するのを待つために使用される 1 つの追加のファイル ハンドルを継承します。子プロセスがこのファイル ハンドルを手動で閉じると、reproc は子プロセスが終了したことを誤って検出します。このハンドルが、子プロセスよりも存続する他のプロセスによってさらに継承される場合、reproc は、子プロセスが終了した場合でも、子プロセスがまだ実行中であることを検出します。データがこのハンドルに書き込まれると、reproc は子プロセスが終了したことを誤って検出します。
(Windows) 子プロセスが終了する前に stdout または stderr ストリームを閉じたかどうかを検出することはできません。子プロセスが終了すると、子プロセスの出力ストリームが閉じられることが親プロセスにのみ通知されます。
(Windows) reproc は、Windows がファイル システム オブジェクトとして使用できるソケットを作成することを前提としています。具体的には、 WSASocket
によって返されるデフォルトのソケットにはXP1_IFS_HANDLES
フラグが設定されている必要があります。 Windows マシンに外部 LSP プロバイダーがインストールされている場合は、この限りではない可能性があります。この場合、追加のサービス プロバイダーを提供しているソフトウェアは廃止されており、今後は使用しないでください (https://docs.microsoft.com/en-us/windows/win32/winsock/ を参照)。階層化されたサービスプロバイダーとアプリケーションの分類)。