gcc — выход (3) зависает в Linux Переполнение стека

У меня есть небольшая программа на C ++, которая пингует другие машины в сети и отправляет информацию о состоянии через другую сеть. Программа запускается как демон, поэтому процесс запуска разветвляется на потомка, а затем вызывает exit, Эта программа кросс-компилируется для работы на двух разных архитектурах: x86 и ARM. Версии GCC — 4.4 и 3.5 соответственно. Я могу скомпилировать и запустить программу на x86, и она работает без нареканий. Однако, когда я запускаю программу на ARM, она зависает каждый раз, когда я звоню exitне только после fork, У меня нет зарегистрированных функций atexit или же on_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
}

2

Решение

Однажды я столкнулся с проблемой 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.

0

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector