AWS SDK for C++をマルチスレッドで利用する場合、Aws::InitAPI
とAws::ShutdownAPI
の呼び出しタイミングでハマったのでメモ。
環境準備
DockerとMinioを利用して開発環境を用意しています。
下記記事の設定や実装をベースにしています。
DockerとMinioでAWS SDK for C++の開発環境を構築する - Qiita
https://qiita.com/kai_kou/items/d160948553504848d380
検証
シングルスレッドで実行
シングルスレッドで実行してみます。main.cpp
のmain
メソッドを以下のように変更します。
(略)
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
メソッドでマルチスレッド実行するように変更して実行してみます。
(略)
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
メソッドに移動してやればひとまず解決です。
(略)
// 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://qiita.com/kai_kou/items/d160948553504848d380
C/C++によるマルチスレッドプログラミング入門 - Qiita
https://qiita.com/nsnonsugar/items/be8a066c6627ab5b052a