3

私はゲームのスレッドネットワークを実行していますが、サーバーがランダムに停止します。ネットワークをテストしている間、複数のクライアントが接続して大量のパケットを送信し、切断してから再度接続します。

私はSFML/ネットワークおよびSFML/システムスレッドでc++を使用しています。接続が確立されるとサーバーで接続をリッスンするスレッドがあり、パケットを送受信するための2つの新しいスレッドが作成されます。イベントハンドラーと送信/受信スレッドは、2つのstd::queuesとデータを共有します。私はgdbを使用してクラッシュをデバッグしようとしていますが、これについてはそれほど経験がないので、助けを求めています。

クラッシュが発生したときのgdbコンソールの入力は次のとおりです。

OUT: 10 1 HELLO
IN: 10 0 LOLOLOL
OUT: 10 1 HELLO
IN: 10 0 LOLOLOL
OUT: 10 1 HELLO
Out thread killed by in thread!
In thread died!
New client connected!
[Thread 0x34992b70 (LWP 16167) exited]
[New Thread 0x3118bb70 (LWP 16186)]
terminate called without an active exception

Program received signal SIGABRT, Aborted.
[Switching to Thread 0x35193b70 (LWP 16166)]
0x00110416 in __kernel_vsyscall ()

バックトレースは次のとおりです。

(gdb) backtrace
#0  0x00110416 in __kernel_vsyscall ()
#1  0x46a0967f in raise (sig=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64
#2  0x46a0afb5 in abort () at abort.c:92
#3  0x47b8af0d in __gnu_cxx::__verbose_terminate_handler () at ../../../../libstdc++-v3/libsupc++/vterminate.cc:95
#4  0x47b88c84 in __cxxabiv1::__terminate (handler=0x47b8adc0 <__gnu_cxx::__verbose_terminate_handler()>) at ../../../../libstdc++-v3/libsupc++/eh_terminate.cc:40
#5  0x47b88cc0 in std::terminate () at ../../../../libstdc++-v3/libsupc++/eh_terminate.cc:50
#6  0x47b8878f in __cxxabiv1::__gxx_personality_v0 (version=1, actions=10, exception_class=890844228, ue_header=0x35193dc0, context=0x35192ea0)
    at ../../../../libstdc++-v3/libsupc++/eh_personality.cc:669
#7  0x46bdbfbe in _Unwind_ForcedUnwind_Phase2 (exc=0x35193dc0, context=0x35192ea0) at ../../../gcc/unwind.inc:175
#8  0x46bdc3a9 in _Unwind_ForcedUnwind (exc=0x35193dc0, stop=0x46b76fc0 <unwind_stop>, stop_argument=0x35193444) at ../../../gcc/unwind.inc:207
#9  0x46b794e2 in _Unwind_ForcedUnwind (exc=0x35193dc0, stop=0x46b76fc0 <unwind_stop>, stop_argument=0x35193444) at ../nptl/sysdeps/pthread/unwind-forcedunwind.c:132
#10 0x46b77141 in __pthread_unwind (buf=<optimized out>) at unwind.c:130
#11 0x46b6f5bb in __do_cancel () at ../nptl/pthreadP.h:265
#12 sigcancel_handler (sig=<optimized out>, si=<optimized out>, ctx=<optimized out>) at nptl-init.c:202
#13 sigcancel_handler (sig=32, si=0x35192f7c, ctx=0x35192ffc) at nptl-init.c:155
#14 <signal handler called>
#15 0x08049930 in out (data=0xb761c798) at src/layer7.cpp:40
#16 0x0804b8d7 in sf::priv::ThreadFunctorWithArg<void (*)(networkdata*), networkdata*>::Run (this=0xb761c7c8) at /usr/local/include/SFML/System/Thread.inl:48
#17 0x00116442 in sf::Thread::Run() () from /home/toni/ProjectRepos/sfml/build/lib/libsfml-system.so.2
#18 0x001166df in sf::priv::ThreadImpl::EntryPoint(void*) () from /home/toni/ProjectRepos/sfml/build/lib/libsfml-system.so.2
#19 0x46b70c5e in start_thread (arg=0x35193b70) at pthread_create.c:305
#20 0x46ab4b4e in clone () at ../sysdeps/unix/sysv/linux/i386/clone.S:133

これがsrc/layer7.cppのスレッドコードです

void out(networkdata * data) {
    bool running = true;
    while(running) {
        if(data->pipe_out->pipe_empty() == false) {
            sf::Packet packet = data->pipe_out->pop_message();
            if(data->socket->Send(packet) == sf::Socket::Disconnected) {
                data->thread_in->Terminate();
                std::cout << "In thread killed by out thread!" << std::endl;
                running = false;
            }
        }
    }
    std::cout << "Out thread died!" << std::endl;
}
  • 行40は、while(実行中)の後の最初のifキーワードです。
  • data-> pipe_out-> pipe_empty()は、queue-> empty()への呼び出しです。
  • data-> pipe_out-> pop_message()は、キューからフロントをポップする呼び出しです。
  • 次に、パケットを送信し、接続が切断されていないかどうかを確認します
  • ソケットが切断されると、「in」スレッドが終了し、自身のスレッドが停止します。
4

2 に答える 2

3

data複数のスレッドから同じデータ構造への同時アクセスから保護するために、ロックが必要です。

于 2011-06-06T20:31:39.887 に答える
0

考えられる理由の 1 つは例外です。例外はスレッド内でキャッチする必要があります。また、data->thread_in->Terminate() がキャンセル要求を送信しているように見えます。その場合、確立されたすべてのキャンセル ハンドラが正しく機能していることを確認してください。

于 2011-06-07T08:29:20.223 に答える