唤醒线程在accept()调用时被阻塞

Linux上的套接字问题

我有一个工作线程被accept()调用阻塞。它只是等待传入的网络连接,处理它,然后返回监听下一个连接。

当程序退出的时候,如何发信号通知这个网络工作线程(从主线程)返回从accept()调用,同时仍然能够优雅地退出它的循环并处理它的清理代码。

我尝试过的一些事情

> pthread_kill发送信号。感觉kludgy做这个,加上它不可靠地允许线程做它的关机逻辑。也使程序也终止。如果可能,我想避免信号。
> pthread_cancel。与上述相同。这是对线程的严厉杀戮。那个,线程可能在做别的事情。
>从主线程关闭listen套接字以使accept()中止。这并不可靠。

一些限制:

如果解决方案涉及使监听套接字无阻塞,那很好。但是我不想接受一个解决方案,通过每隔几秒钟的select调用唤醒线程来检查退出条件。

退出的线程条件可能不会与退出的进程相关联。

基本上,我要去的逻辑看起来像这样。

void* WorkerThread(void* args)
{
    DoSomeImportantInitialization();  // initialize listen socket and some thread specific stuff

    while (HasExitConditionBeenSet()==false)
    {
        listensize = sizeof(listenaddr);
        int sock = accept(listensocket, &listenaddr, &listensize);

        // check if exit condition has been set using thread safe semantics
        if (HasExitConditionBeenSet())
        {
            break;
        }

        if (sock < 0)
        {
            printf("accept returned %d (errno==%d)\n", sock, errno);
        }
        else
        {
            HandleNewNetworkCondition(sock, &listenaddr);
        }
    }

    DoSomeImportantCleanup(); // close listen socket, close connections, cleanup etc..
    return NULL;
}

void SignalHandler(int sig)
{
    printf("Caught CTRL-C\n");
}

void NotifyWorkerThreadToExit(pthread_t thread_handle)
{
    // signal thread to exit
}

int main()
{
    void* ptr_ret= NULL;
    pthread_t workerthread_handle = 0;

    pthread_create(&workerthread, NULL, WorkerThread, NULL);

    signal(SIGINT, SignalHandler);

    sleep((unsigned int)-1); // sleep until the user hits ctrl-c

    printf("Returned from sleep call...\n");

    SetThreadExitCondition(); // sets global variable with barrier that worker thread checks on

    // this is the function I'm stalled on writing
    NotifyWorkerThreadToExit(workerthread_handle);

    // wait for thread to exit cleanly
    pthread_join(workerthread_handle, &ptr_ret);

    DoProcessCleanupStuff();

}
您可以使用管道通知您要退出的线程。然后,您可以在管道和监听套接字上选择一个select()调用。

例如(编译但未完全测试):

// NotifyPipe.h
#ifndef NOTIFYPIPE_H_INCLUDED
#define NOTIFYPIPE_H_INCLUDED

class NotifyPipe
{
        int m_receiveFd;
        int m_sendFd;

    public:
        NotifyPipe();
        virtual ~NotifyPipe();

        int receiverFd();
        void notify();
};

#endif // NOTIFYPIPE_H_INCLUDED

// NotifyPipe.cpp

#include "NotifyPipe.h"

#include <unistd.h>
#include <assert.h>
#include <fcntl.h>

NotifyPipe::NotifyPipe()
{
    int pipefd[2];
    int ret = pipe(pipefd);
    assert(ret == 0); // For real usage put proper check here
    m_receiveFd = pipefd[0];
    m_sendFd = pipefd[1];
    fcntl(m_sendFd,F_SETFL,O_NONBLOCK);
}


NotifyPipe::~NotifyPipe()
{
    close(m_sendFd);
    close(m_receiveFd);
}


int NotifyPipe::receiverFd()
{
    return m_receiveFd;
}


void NotifyPipe::notify()
{
    write(m_sendFd,"1",1);
}

然后用receiverFd()选择,并使用notify()通知终止。

http://stackoverflow.com/questions/2486335/wake-up-thread-blocked-on-accept-call

本站文章除注明转载外,均为本站原创或编译
转载请明显位置注明出处:唤醒线程在accept()调用时被阻塞