FreeBSD下accept函数不能被信号中断的问题

发布于 2022-09-12 02:47:46 字数 6198 浏览 13 评论 0

本帖最后由 happy_fish100 于 2010-08-09 18:48 编辑

FastDFS 2.0改造中,kill 服务进程时,如kill fdfs_storaged,服务进程在Linux可以正常退出,在FreeBSD下会一直运行。
经过调试,发现FreeBSD下accept这个堵塞式的系统调用没有被kill中断的缘故。
解决方法,当使用kill -TERM或者kill -INT杀掉进程,当程序收到退出信号时,连接一下自己即可结束堵塞的accept调用。
因为在Linux中是正常的,所以代码中采用了定时器,1秒后才发出连接自己的动作。代码如下:

static bool bAcceptEndFlag = false;  //accept normal end flag

int main(int argc, char *argv[])
{
        ...

        bAcceptEndFlag = false;  

        storage_accept_loop(sock);  //循环accept
        bAcceptEndFlag = true;

        ...
}

//定时器处理函数
static void sigAlarmHandler(int sig)
{
        TrackerServerInfo server;

        if (bAcceptEndFlag)
        {
                return;
        }

        logDebug("file: "__FILE__", line: %d, "
                "signal server to quit...", __LINE__);

        if (*g_bind_addr != '')
        {
                strcpy(server.ip_addr, g_bind_addr);
        }
        else
        {
                strcpy(server.ip_addr, "127.0.0.1");
        }
        server.port = g_server_port;
        server.sock = -1;

        if (tracker_connect_server_ex(&server, 1) != 0)
        {
                return;
        }

        fdfs_quit(&server);
        tracker_disconnect_server(&server);

        logDebug("file: "__FILE__", line: %d, "
                "signal server to quit done", __LINE__);
}

//退出信号处理函数
static void sigQuitHandler(int sig)
{
        if (!bTerminateFlag)
        {
                set_timer(1, 1, sigAlarmHandler);

                bTerminateFlag = true;
                g_continue_flag = false;

                logCrit("file: "__FILE__", line: %d, "
                        "catch signal %d, program exiting...",
                        __LINE__, sig);
        }
}

//设置定时器
int set_timer(const int first_remain_seconds, const int interval,
                void (*sighandler)(int))
{
        struct itimerval value;
        struct sigaction act;

        memset(&act, 0, sizeof(act));
        sigemptyset(&act.sa_mask);
        act.sa_handler = sighandler;
        if(sigaction(SIGALRM, &act, NULL) < 0)
        {
                logError("file: "__FILE__", line: %d, "
                        "call sigaction fail, errno: %d, error info: %s",
                        __LINE__, errno, strerror(errno));
                return errno != 0 ? errno : EINVAL;
        }

        memset(&value, 0, sizeof(value));
        value.it_interval.tv_sec = interval;
        value.it_value.tv_sec = first_remain_seconds;
        if (setitimer(ITIMER_REAL, &value, NULL) < 0)
        {
                logError("file: "__FILE__", line: %d, "
                        "call setitimer fail, errno: %d, error info: %s",
                        __LINE__, errno, strerror(errno));
                return errno != 0 ? errno : EINVAL;
        }

        return 0;
}

以上是我的解决办法。看看大家有没有更好的解决方法,呵呵。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文