0

信号を処理しようとして問題が発生しています...

マルチスレッドアプリケーションがあり、使用しているライブラリのシステムコールを中断するシグナルを受信します。調査の結果、シグナルが処理されない場合、アプリケーションのランダムスレッドに送信されることがわかりました。私が使用しているライブラリから、アプリケーションでシグナルを使用していないことを確認しました。私もそうではありません。これが私のメインドライバークラスです。

void sig_handler(int signum)
{
    cout << "Signal Handle: " << signum << endl;
    signal(signum, SIG_IGN);
}


class Driver
{
    public:
        Driver();
        void LaunchLog();
        void logonListen();
};

Driver::Driver()
{
    pthread_t logThread;
    pthread_create(&logThread, NULL, LaunchLogThread, (void*) this);
    pthread_detach(logThread);

    pthread_t listenThread;
    pthread_create(&listenThread, NULL, LaunchListenThread, (void*)this);
    pthread_detach(listenThread);

    bool running = true;

    while(running)
    {
        //Simple loop to resemble a menu for the console
    }
}

void Driver::logonListen()
{
    char buffer[256];

    int logonPort = BASEPORT;
    int sockfd;
    struct sockaddr_in serv_addr, cli_addr;
    socklen_t clilen;

    //initialize socket
    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if(sockfd < 0){
        perror("Error opening socket");
        exit(1);
    }
    bzero((char*)&serv_addr, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = INADDR_ANY;
    serv_addr.sin_port = htons(logonPort);

    //bind socket to our address
    if(bind(sockfd,(struct sockaddr*) &serv_addr, sizeof(serv_addr)) < 0)
    {
        perror("Error on bind");
        exit(1);
    }

    clilen = sizeof(struct sockaddr_in);

    int n;
    int nextUser = 2;
    char reply[32];

    while(1)
    {
        //Wait for incoming connection on a socket
    }
}

void Driver::LaunchLog()
{
    Logger::Instance()->WriteToFile();
}

void* LaunchListenThread(void* ptr)
{
    Driver* driver = (Driver*) ptr;
    driver->logonListen();
}

int main()
{
    signal (SIGHUP, sig_handler);
    signal (SIGINT, sig_handler);
    signal (SIGQUIT, sig_handler);
    signal (SIGILL, sig_handler);
    signal (SIGTRAP, sig_handler);
    signal (SIGFPE, sig_handler);
    signal (SIGKILL, sig_handler);
    signal (SIGUSR1, sig_handler);
    signal (SIGSEGV, sig_handler);
    signal (SIGUSR2, sig_handler);
    signal (SIGPIPE, sig_handler);
    signal (SIGALRM, sig_handler);
    signal (SIGTERM, sig_handler);
    signal (SIGCHLD, sig_handler);
    signal (SIGCONT, sig_handler);
    signal (SIGSTOP, sig_handler);
    signal (SIGTSTP, sig_handler);
    signal (SIGTTIN, sig_handler);
    signal (SIGTTOU, sig_handler);
    signal (SIGABRT, sig_handler);
    Driver driver;
    return 0;
}

信号を処理できません。中断されたシステムコールは忍び寄り続け、私のシグナルハンドラーは決して使用されません。コンソールでCTRL+Cを押しても、SIGINTが処理されるのではなく、プログラムが中断して終了します。ハンドラーを正しくインストールしていませんか?

すべての信号を処理し、発生した場合にそれらを無視する方法はありますか?

ありがとう

4

2 に答える 2

1

いくつかのこと。まず、の戻り値を確認する必要がありますsignal()。シグナルハンドラーのインストールに問題がある場合は、SIG_ERRを返す可能性があります(これらのシグナルの一部はトラップできないため、少なくとも一部のケースではおそらく発生します)。stdio第2に、シグナルハンドラーで/関数を使用iostreamすると、非同期(同じ機能を使用している可能性のあるプログラム内の他の何かに関して)の性質のために問題が発生する可能性があります。そして第3に、シグナルハンドラーでは、最初に呼び出された場合でも、そのシグナルを無視するように設定しているため、そのシグナルの後続のインスタンス(キャッチ可能なものであると想定)は単に無視されます。そもそもそれらを無視したい場合は、ハンドラーを作成する必要はありませsignal(SIG<whatever>, SIG_IGN)main()

于 2012-09-24T15:31:53.260 に答える
1

SA_RESTARTフラグを指定してsigaction(2)を使用してシグナルを無視し、システムコールが中断されるのではなく再開されるようにします。

struct sigaction sa;
sa.sa_hanlder = SIG_IGN;
sa.sa_flags = SA_RESTART;

sigaction(SIGALRM, &sa);
sigaction(SIGPIPE, &sa);
/* repeat for all the signals you want to ignore */

ctrl-Cを使用してプログラムを停止することができないため、SIGINTなどを無視したくない場合があることに注意してください。同様に、SIGSEGVを無視すると、プログラムが終了するのではなく、バグが含まれている場合にプログラムがハングする可能性があります。

編集

あなたも図書館も信号を使用していないというあなたの説明は完全には真実ではありません-信号はどこかから来ています、そしてあなたがしていることが内部で信号を使用していることに気付いていない場合があります。どこかでアラームやイティマーを使用している場合、それらには信号が含まれます。sig_handlerが本当に呼び出されていない場合、それは他の誰か(あなたのライブラリ?)がそれを置き換えるためにシグナルハンドラーをインストールしていることを意味します。

それでも信号がどこから来ているのかわからない場合は、デバッガーで実行し、デバッガーの信号デバッグ機能を有効にすることができます(必要な場合)。これにより、少なくとも、どの信号が発生しているか、どこで発生しているかがわかります。

一般に、システムコールでは、常にエラーをチェックする必要があります。予期せずエラーEINTRが表示された場合は、システムコールをループしてやり直す必要があります。

于 2012-09-24T16:01:03.460 に答える