0

現在、ソケットを使用して C++ でサーバーを実装しようとしています。ブロッキング pselect でスタックするまで SIGINT シグナルをブロックすることで、競合状態を防止しようとしています。そこから終了し、ループ変数を変更してから、スレッドを終了する必要があります。これを機能させようとする私の試みから、pselect() に到達したように見えますが、私のコードを使用して中断されることはありません。どんな助けでも大歓迎です。

Listener.h:

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

class CListener
{
public:
    CListener();
    void quitListener(void);

private:
    void* InitListener(void);
    static void* StartListenerThread(void* context);

    static bool mbListening;
    pthread_t mtThreadID;
};

リスナー.cpp

#include <iostream>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <pthread.h>
#include <signal.h>
#include <errno.h>

#include "Listener.h"

bool CListener::mbListening = true;

CListener::CListener()
{
    mbListening = true;
    mtThreadID = 0;
    pthread_create(&mtThreadID, NULL, &CListener::StartListenerThread, this);
}

void* CListener::StartListenerThread(void* context)
{
    return ((CListener*)context)->InitListener();
}

void* CListener::InitListener()
{
    sigset_t tSignalSet;
    sigset_t tOriginalSignalSet;

    sigemptyset(&tSignalSet);
    sigaddset(&tSignalSet, SIGINT);
    sigprocmask(SIG_BLOCK, &tSignalSet, &tOriginalSignalSet);

    FD_ZERO(&tConnectionSet);
    FD_SET(0, &tConnectionSet);

    while(mbListening)
    {
            tSelectSet = tConnectionSet;
            std::cout << "Reached pselect\n";
            nReadyConnections = pselect(nSelectSocket+1, &tSelectSet,
                                    NULL, NULL, NULL, &tOriginalSignalSet);
            std::cout << "Broke out of pselect\n";
            if(nReadyConnections < 0 && errno == EINTR)
            {
                mbListening = false;
            }
    }

    pthread_exit(NULL);

    return NULL;
}

void CListener::quitListener()
{
    raise(SIGINT);
}

指を交差させてすべてを正しくコピーしている限り、実行できるはずです。

CListener tListener = CListener();

usleep(20000);

tListener.quitListener();

出力はターミナルに表示されます。私の最終的な目標は、pselect が中断される可能性があり、後に発生する可能性のある処理を中断せず、スレッドを正常に閉じることができるようにすることです。(pselect でブロック > SIGINT を受信 > pselect を中断 > ループに戻る > 終了して終了)

4

1 に答える 1

0

私は自分の問題を解決しました。私はスレッドを生成しているので、以下に示すように、それを可能にする関数を追加するだけでなく、シグナル ハンドラーを追加する必要がありました。

void CListener::quitListener()
{
    pthread_kill(mtThreadID,SIGINT);
}

void CListener::installSIGINTHandler()
{
    signal(SIGINT, CListener::SIGINTHandler);
}

void CListener::SIGINTHandler(int signo)
{
    mbListening = false;
}

また、sig mask の設定を次のように変更する必要がありました。

pthread_sigmask(SIG_BLOCK, &tSignalSet, &tOriginalSignalSet);
于 2013-05-23T17:14:19.950 に答える