繁体   English   中英

exit(3)在Linux C ++中挂起

[英]exit(3) hangs in Linux C++

我有一个小的C ++程序,可以ping网络上的其他计算机,并通过另一个网络发送状态信息。 该程序作为守护程序运行,因此启动过程会派生一个孩子,然后调用exit 该程序是交叉编译的,可以在两种不同的体系结构上运行:x86和ARM。 GCC版本分别为4.4和3.5。 我可以在x86上编译并运行该程序,它可以完美运行。 但是,当我在ARM上运行程序时,只要我调用exit ,它就会挂起,而不仅仅是在fork 我没有向atexiton_exit注册的函数。 以下是我的包括:

#include <cstdio>
#include <cstdlib>
#include <cstring>

#include <iostream>
#include <sstream>
#include <string>
#include <set>
#include <vector>

#include <boost/bind.hpp>
#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include "telnet_client.h"

#include <stdint.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <netdb.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <syslog.h>
#include <customlib1.h>
#include <customlib2.h>

以下是我的GCC命令:

arm-none-linux-gnueabi-g++ -Wall -DBUILDSTAMP="\"`date '+%F %T'`\"" -g -ggdb -O0 -I/usr/local/arm/arm-2007q1/arm-none-linux-gnueabi/libc/usr/include -DEMBEST_ARM -I/usr/local/share/arm/boost/src -I../include/ -I../include_rms -c can_wifid.cpp -o can_wifid.o
arm-none-linux-gnueabi-g++ -Wall -DBUILDSTAMP="\"`date '+%F %T'`\"" -g -ggdb -O0 -I/usr/local/arm/arm-2007q1/arm-none-linux-gnueabi/libc/usr/include -DEMBEST_ARM -I/usr/local/share/arm/boost/src -I../include/ -I../include_rms -c telnet_client.cpp -o telnet_client.o
arm-none-linux-gnueabi-g++ -Wall -DBUILDSTAMP="\"`date '+%F %T'`\"" -g -ggdb -O0 -I/usr/local/arm/arm-2007q1/arm-none-linux-gnueabi/libc/usr/include -DEMBEST_ARM -I/usr/local/share/arm/boost/src can_wifid.o telnet_client.o -L/usr/local/arm/arm-2007q1/arm-none-linux-gnueabi/libc/usr/lib  -L../lib_embest_arm -L../lib_rms_embest_arm -Wl,-Bdynamic -lutilities -lboost_system -lboost_thread -lcanprovider -lembestcan -o can_wifid

即使只是使用getopt解析我的命令行参数,然后在版本消息后调用exit也会导致此问题(在我的程序中是最简单的情况)。 有没有人遇到过这样的事情, exit只是挂着?

编辑:为主要功能的第一部分添加了代码:

struct canwifid_options
{
public:
bool daemon_mode;
int verbosity;

canwifid_options()
{
    this->daemon_mode = false;
    this->verbosity = LOG_NOTICE;
}
};

static canwifid_options options;

int main(int argc, char * argv[])
{
int LoggingOptions = LOG_CONS|LOG_NDELAY|LOG_PID;
pid_t Pid;

ParseCommandLine(argc, argv);

if (!options.daemon_mode)
{
    LoggingOptions |= LOG_PERROR;
}

openlog("can_wifid", LoggingOptions, LOG_USER);

setlogmask(LOG_UPTO(options.verbosity));

if (options.daemon_mode)
{
    Pid = fork();

    if (Pid < 0)
    {
        // couldn't fork off and create a child process
        // log it, %m is a special syslog flag
        syslog(LOG_CRIT, "Unable to create daemon [Error: %m]");
        exit(ESRCH);
    }
    else if (Pid > 0)
    {
        // we're the parent, so we're done and out of here
        exit(EXIT_SUCCESS);
    }
    else
    {
        // we're the child, take control of the session.
        setsid();

        // change to the root directory so we don't retain unnecessary control
        // of any mounted volumes
        chdir("/");

        // clear our file mode creation mask
        umask(0000);
    }
}
else
{
    // get our process ID
    Pid = getpid();
}

syslog(LOG_INFO, "Running as %s", options.daemon_mode ? "daemon" : "standalone");

    // Network code here, snipped for clarity
}

并有ParseCommandLine函数:

static void ParseCommandLine(int argc, char *argv[])
{
int c;

while ((c = getopt(argc, argv, "dhqvDV?")) > 0)
{
    switch (c)
    {
        case 'd':
            options.daemon_mode = true;
            break;
        case 'V':
            VersionMessage(argv);
            exit(EXIT_SUCCESS);
            break;
        case 'q':
            options.verbosity = LOG_WARNING;
            break;
        case 'v':
            options.verbosity = LOG_INFO;
            break;
        case 'D':
            options.verbosity = LOG_DEBUG;
            break;
        case 'h':
        case '?':
        default:
            HelpMessage(argv);
            exit(EXIT_SUCCESS);
            break;
    }
}

return; //done
}

我曾经遇到的一个问题是,调用exit尝试退出并调用全局析构函数,而没有尝试展开堆栈或为栈上的本地对象调用任何析构函数。 如果您具有全局析构函数可能需要的任何类型的锁,这很容易体现出来。 例如,该程序在出口(实际上在全局dtor中)死锁:

#include <iostream>
#include <mutex>

std::mutex  lock;

class A {
public:
    A() {
        std::lock_guard<std::mutex> acquire(lock);
        std::cout << "ctor A" << std::endl;
    }
    ~A() {
        std::lock_guard<std::mutex> acquire(lock);
        std::cout << "dtor A" << std::endl;
    }
};

A a;

int main()
{
    std::lock_guard<std::mutex> acquire(lock);
    exit(0);
}

现在,您的问题可能完全不同,但是很可能与全局析构函数中的某些行为有关,这是因为堆栈中的某些对象没有被正确销毁而导致行为异常。

如果要在正确展开堆栈时退出(这是RAII结构化代码所必需的),则不能调用exit。 相反,您需要引发一个(仅)在main中捕获并导致main返回的异常。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM