チケット #31357

urlモジュールで負荷をかけるとSIGSEGV

登録: 2013-05-14 17:51 最終更新: 2013-08-22 13:57

報告者:
担当者:
チケットの種類:
状況:
完了
コンポーネント:
マイルストーン:
(未割り当て)
優先度:
5 - 中
重要度:
5 - 中
解決法:
なし
ファイル:
1

詳細

v3.1.0-devel + urlモジュールを使い、TPC-WでCL=2000の負荷をかけるとl7vsdがセグメンテーションフォルトで落ちる。

オプションは以下。

module = url -P ".*Home.jsp.*" -RS 192.168.100.139:80 -P ".BestSellers.jsp.*" -RS 192.168.100.140:80 -P ".*" -RS 192.168.100.139:80 192.168.100.140:80

チケットの履歴 (8 件中 3 件表示)

2013-05-14 17:51 更新者: hiroakinakano
  • 新しいチケット "urlモジュールで負荷をかけるとSIGSEGV" が作成されました
2013-05-16 10:15 更新者: hiroakinakano
コメント
落ちた箇所は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を見るに、モジュール全体がマルチスレッドセーフなコードになっていないと思われる。
2013-05-16 14:38 更新者: hiroakinakano
コメント
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したアドレスと
かぶって、セグメンテーションフォルトで落ちたんじゃない?
2013-05-20 10:48 更新者: 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)

2013-05-28 17:35 更新者: 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として添付しておきます。

2013-08-09 14:36 更新者: takeda_kenji
コメント

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にマージしたいと思います。

2013-08-22 13:57 更新者: hiroakinakano
  • 状況オープン から 完了 に更新されました
  • チケット完了時刻2013-08-22 13:57 に更新されました
コメント

gitのmasterで対処にあるのを確認しましたので、チケットをcloseします。

添付ファイルリスト

編集

ログインしていません。ログインしていない状態では、コメントに記載者の記録が残りません。 » ログインする