urlモジュールで負荷をかけるとSIGSEGV
落ちた箇所は3パターン。 1. handle_realserver_selectのL2614、rslist_list_it.clear(); 2. おなじくL2611のuseScheduleTCP()を呼び出して、その中のschedule_tcp() 3. failover後セカンダリでは、hancle_client_recv()のL1686、buffer1 = new char[buffer_size]; 当初は1から該当箇所のロックのスコープ間違いかと思ったが、2と3を見るに、モジュール全体がマルチスレッドセーフなコードになっていないと思われる。
3番目のhandle_client_recv()のnewで落ちたやつですが、coreファイル解析で別のスレッド(おそらく対になるdown_stream_thread)で condition_timewait以外で落ちているのを見つけて、その落ちている箇所を見てみました。 handle_realserver_recv()のL4546です。ここ、以下のようなコードになっています。 if (receive_data_it == session_data->receive_data_map.end()) { receive_data recv_data; => session_data->receive_data_map[rs_endpoint] = recv_data; } ・・・この書き方、なんかおかしくない?(汗) recv_dataをnewするなり、なんなりして、そのアドレスを代入しないといけないんじゃない? 宣言だけして、アドレス不定のまま、しかも値をアドレスとして代入してるように見えるよ? アドレスとして変な値が入ったから、対になるup_stream_threadのhandle_client_recieveのnewしたアドレスと かぶって、セグメンテーションフォルトで落ちたんじゃない?
hiroakinakano への返信
{{{ 落ちた箇所は3パターン。 1. handle_realserver_selectのL2614、rslist_list_it.clear(); 2. おなじくL2611のuseScheduleTCP()を呼び出して、その中のschedule_tcp() 3. failover後セカンダリでは、hancle_client_recv()のL1686、buffer1 = new charbuffer_size; 当初は1から該当箇所のロックのスコープ間違いかと思ったが、2と3を見るに、モジュール全体がマルチスレッドセーフなコードになっていないと思われる。 }}}
1,2番のパターンについてです。
protocol_module_url.h
152 std::list< std::list< realserver>::iterator > rslist_it_list;
153 std::list< std::list< realserver>::iterator >::iterator rslist_it_list_it;
これらのパラメータは仮想サービス単位で1つとなる(virtualservice_tcp.cppの648行目より)ので、
ある仮想サービスに紐づくUPスレッド間で共有されます。
ゆえに、これらを更新する操作が行われている以下の箇所で
ダウンしてしまったのではないかと思います。
protocol_module_url.cpp
2611 useScheduleTCP( thread_id, rslist_it_list, rs_endpoint );
2614 rslist_it_list.clear();
対策としては、単純にrslist_it_listやrslist_it_list_itをmutexを使ってガードすればよいはずですが、
そもそもこれらの変数をヘッダファイルに書かないようにしたほうが良いですよね。
(その場合どう書き直せばよいのかというのは… 申し訳ありませんが、まだ考えられていませんorz)
takeda_kenji への返信
hiroakinakano への返信
{{{ 落ちた箇所は3パターン。 1. handle_realserver_selectのL2614、rslist_list_it.clear(); 2. おなじくL2611のuseScheduleTCP()を呼び出して、その中のschedule_tcp() 3. failover後セカンダリでは、hancle_client_recv()のL1686、buffer1 = new charbuffer_size; 当初は1から該当箇所のロックのスコープ間違いかと思ったが、2と3を見るに、モジュール全体がマルチスレッドセーフなコードになっていないと思われる。 }}}
1,2番のパターンについてです。
protocol_module_url.h
152 std::list< std::list< realserver>::iterator > rslist_it_list;
153 std::list< std::list< realserver>::iterator >::iterator rslist_it_list_it;
これらのパラメータは仮想サービス単位で1つとなる(virtualservice_tcp.cppの648行目より)ので、
ある仮想サービスに紐づくUPスレッド間で共有されます。
ゆえに、これらを更新する操作が行われている以下の箇所で ダウンしてしまったのではないかと思います。
protocol_module_url.cpp
2611 useScheduleTCP( thread_id, rslist_it_list, rs_endpoint );
2614 rslist_it_list.clear();
対策としては、単純にrslist_it_listやrslist_it_list_itをmutexを使ってガードすればよいはずですが、
そもそもこれらの変数をヘッダファイルに書かないようにしたほうが良いですよね。
(その場合どう書き直せばよいのかというのは… 申し訳ありませんが、まだ考えられていませんorz)
1、2番のパターンについて、fix_patch書いてみました。
とりあえず動きました。fix_1.patchとして添付しておきます。
hiroakinakano への返信
takeda_kenji への返信
hiroakinakano への返信
{{{ 落ちた箇所は3パターン。 1. handle_realserver_selectのL2614、rslist_list_it.clear(); 2. おなじくL2611のuseScheduleTCP()を呼び出して、その中のschedule_tcp() 3. failover後セカンダリでは、hancle_client_recv()のL1686、buffer1 = new charbuffer_size; 当初は1から該当箇所のロックのスコープ間違いかと思ったが、2と3を見るに、モジュール全体がマルチスレッドセーフなコードになっていないと思われる。 }}}
1,2番のパターンについてです。
protocol_module_url.h
152 std::list< std::list< realserver>::iterator > rslist_it_list;
153 std::list< std::list< realserver>::iterator >::iterator rslist_it_list_it;
これらのパラメータは仮想サービス単位で1つとなる(virtualservice_tcp.cppの648行目より)ので、
ある仮想サービスに紐づくUPスレッド間で共有されます。
ゆえに、これらを更新する操作が行われている以下の箇所で ダウンしてしまったのではないかと思います。
protocol_module_url.cpp
2611 useScheduleTCP( thread_id, rslist_it_list, rs_endpoint );
2614 rslist_it_list.clear();
対策としては、単純にrslist_it_listやrslist_it_list_itをmutexを使ってガードすればよいはずですが、
そもそもこれらの変数をヘッダファイルに書かないようにしたほうが良いですよね。
(その場合どう書き直せばよいのかというのは… 申し訳ありませんが、まだ考えられていませんorz)1、2番のパターンについて、fix_patch書いてみました。
とりあえず動きました。fix_1.patchとして添付しておきます。
パッチ作成ありがとうございます。
「rslist_it_list_segv_fix」というブランチを切って、そちらでパッチを当てました。
また、パッチを当てたコードで40回ほどサービス継続性検証(定常負荷:クライアント数15000、試験開始一定時間後にl7vsdダウンによるフェールオーバ発生)を
実施したところ、特に問題が発生しないことを確認しました。(パターン3についてもこのパッチで解決したかも…)
よって、先述のブランチをmasterにマージしたいと思います。
gitのmasterで対処にあるのを確認しましたので、チケットをcloseします。
v3.1.0-devel + urlモジュールを使い、TPC-WでCL=2000の負荷をかけるとl7vsdがセグメンテーションフォルトで落ちる。
オプションは以下。