AWS SDK for C++をマルチスレッドで利用する場合、Aws::InitAPI
とAws::ShutdownAPI
の呼び出しタイミングでハマったのでメモ。
環境準備
DockerとMinioを利用して開発環境を用意しています。
下記記事の設定や実装をベースにしています。
DockerとMinioでAWS SDK for C++の開発環境を構築する – Qiita
https://cloudpack.media/46547
検証
シングルスレッドで実行
シングルスレッドで実行してみます。main.cpp
のmain
メソッドを以下のように変更します。
main.cpp
(略) int main() { // シングルスレッドで実行 put_object("hoge1.txt"); put_object("hoge2.txt"); return 0; }
コンテナ内
# cd /cpp-dev/build # cmake .. # cmake --build . # ./main hoge1.txt Done! hoge2.txt Done!
問題なく実行できました。
Minioが利用するディレクトリにファイルが保存されたのも確認できます。
> tree data/hoge data/hoge/ ├── hoge1.txt └── hoge2.txt > cat data/hoge/hoge1.txt hoge!
マルチスレッドで実行
main.cpp
のmain
メソッドでマルチスレッド実行するように変更して実行してみます。
main.cpp
(略) int main() { // マルチスレッドで実行 std::thread th_1(put_object, "hoge3.txt"); std::thread th_2(put_object, "hoge4.txt"); th_1.join(); th_2.join(); return 0; }
コンテナ内
# cmake --build . # ./main hoge3.txt Done! main: /aws-sdk-cpp/aws-cpp-sdk-core/source/monitoring/MonitoringManager.cpp:55: void Aws::Monitoring::OnRequestSucceeded( const String&, const String&, const std::shared_ptr<const Aws::Http::HttpRequest>&, const HttpResponseOutcome&, const Aws::Monitoring::CoreMetricsCollection&, Aws::Vector<void*>& ): Assertion `s_monitors' failed. Aborted
1つめは実行されて、2つめがエラーになりました。Assertion
s_monitors’ failed.あたりで調べてみると
、Aws::InitAPIと
Aws::ShutdownAPI` の実行タイミングに問題がありそうでした。
How to handle Aws::ShutdownAPI with multiple threads on Windows? · Issue #1050 · aws/aws-sdk-cpp
https://github.com/aws/aws-sdk-cpp/issues/1050
c++ – Why does an assert(s_monitors) in MonitoringManager::OnRequestSucceeded() fail? – Stack Overflow
https://stackoverflow.com/questions/54290073/why-does-an-asserts-monitors-in-monitoringmanageronrequestsucceeded-fail
InitAPI
、PutObject
、ShutdownAPI
の実行後にログを仕込んてみるとPutObject
実行時に落ちてるみたいです。マルチスレッドなので、hoge3.txt
とhoge4.txt
の実行タイミングが入れ替わることもあります。
# ./main hoge3.txt InitAPI hoge4.txt InitAPI hoge3.txt PutObject hoge3.txt Done! hoge3.txt ShutdownAPI main: /aws-sdk-cpp/aws-cpp-sdk-core/source/monitoring/MonitoringManager.cpp:55: void Aws::Monitoring::OnRequestSucceeded( const String&, const String&, const std::shared_ptr<const Aws::Http::HttpRequest>&, const HttpResponseOutcome&, const Aws::Monitoring::CoreMetricsCollection&, Aws::Vector<void*>& ): Assertion `s_monitors' failed. Aborted
原因と解決策
おそらくですが、Aws::InitAPI
とAws::ShutdownAPI
がグローバルな初期化関数とクリーンアップ機能なので、マルチスレッドスレッド中に呼び出すとダメっぽいです。
なので、put_object
メソッド内で呼び出しているAws::InitAPI
とAws::ShutdownAPI
をmain
メソッドに移動してやればひとまず解決です。
main.cpp
(略) // put_objectメソッド内のInitAPIとShutdownAPI呼び出しをなくす int main() { Aws::SDKOptions options; Aws::InitAPI(options); // マルチスレッドで実行 std::thread th_1(put_object, "hoge3.txt"); std::thread th_2(put_object, "hoge4.txt"); th_1.join(); th_2.join(); Aws::ShutdownAPI(options); return 0; }
Aws::ShutdownAPI
についてはAWS公式のGitHubリポジトリにあるサンプルだと複数回実行しても問題なさそうな実装になっているのですが、シングルスレッドで実行するので問題が発生しないのだと思います。
マルチスレッドで実行する場合はAws::InitAPI
と同様にメインスレッドで呼び出すのが無難みたいです。
aws-doc-sdk-examples/s3-demo.cpp at master · awsdocs/aws-doc-sdk-examples
https://github.com/awsdocs/aws-doc-sdk-examples/blob/master/cpp/example_code/s3/s3-demo.cpp
参考
How to handle Aws::ShutdownAPI with multiple threads on Windows? · Issue #1050 · aws/aws-sdk-cpp
https://github.com/aws/aws-sdk-cpp/issues/1050
c++ – Why does an assert(s_monitors) in MonitoringManager::OnRequestSucceeded() fail? – Stack Overflow
https://stackoverflow.com/questions/54290073/why-does-an-asserts-monitors-in-monitoringmanageronrequestsucceeded-fail
aws-doc-sdk-examples/s3-demo.cpp at master · awsdocs/aws-doc-sdk-examples
https://github.com/awsdocs/aws-doc-sdk-examples/blob/master/cpp/example_code/s3/s3-demo.cpp
DockerとMinioでAWS SDK for C++の開発環境を構築する – Qiita
https://cloudpack.media/46547
C/C++によるマルチスレッドプログラミング入門 – Qiita
https://qiita.com/nsnonsugar/items/be8a066c6627ab5b052a