У меня есть небольшая программа на C++, которая пингорует другие компьютеры в сети и отправляет информацию о статусе через другую сеть. Программа запускается как демон, поэтому процесс запуска выдает дочерние элементы, а затем вызывает exit
. Эта программа перекрестно скомпилирована для работы на двух разных архитектурах: x86 и ARM. Версия GCC составляет 4,4 и 3,5 соответственно. Я могу скомпилировать и запустить программу на x86, и она работает безупречно. Однако, когда я запускаю программу на ARM, она зависает в любое время, когда я звоню exit
, а не сразу после fork
. У меня нет функций, зарегистрированных с atexit
или on_exit
. Ниже приведены мои включает в себя:exit (3) зависает в Linux C++
#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>
Ниже приведены мои НКУ команды:
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
просто зависает?
EDIT: Добавлен код для первой части главной функции:
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
}
Давайте посмотрим код из fork(), чтобы выйти(). – wallyk
Вы уже пробовали «Hello, World», скрем-скомпилированный? Сбой программы, если вы только что вернулись из основного? Если вы можете сделать версию без сбоев, разверните ее по строкам, чтобы создать самую простую сбойную версию. – hyde
Обратите внимание, что среда выполнения обычно добавляет обработчики atexit, например. закрыть FILE * или запустить деструкторы глобальных объектов C++. Это может обеспечить понимание, если вы сможете захватить вывод 'strace', когда процесс зависает, или подключить отладчик и создать обратную трассировку. Другое дело отметить, что многопоточные программы forking() очень опасны, так как они несут большой потенциал для условий гонки в замках (а не только ваши собственные, но внутренние мьютексы, используемые malloc, FILE * и т. Д.) - это зависит от когда вилка выполнена. – nos