我有一个可以在其他Linux平台上运行的代码库,比如CentOS,Redhat,...... 但它在我的FreeBSD 10.1发行版中失败了。 我这里有一个监视器处理程序,它每隔10秒执行相同的操作。
前几次正常,它返回60(超时),所以monitor_handler继续运行。但是当它返回1(不允许操作)时,处理程序将停止并锁定在pthread_mutex_lock。
我尝试删除getOSName()并从处理程序中打印一些值,处理程序可以继续运行。但是我不确定它是否只是时间问题,也许它会在更多天后失败。
我也尝试不在getOSName()中使用popen,它可以运行更长时间但仍然会挂起。但是ret是60(超时)并且在pthread_mutex_lock之后挂起。
有人对这三种情况有所了解吗? FreeBSD中是否存在此功能的错误,或者我不能像这样使用它。 还有其他方法可以在FreeBSD中实现等待和锁定吗?
感谢。
=========更新完整代码以重现====================
pthread_t monitor_thread;
pthread_mutex_t monitor_lock;
pthread_cond_t monitor_condition;
int start() {
if (getServiceCount() > 0) {
printf("service existed\n");
printErrLog(" ", "service existed");
return EXIT_FAILURE;
}
if (initIni() == EXIT_FAILURE)
exit(EXIT_FAILURE);
struct sigaction act;
//signal terminate call back
memset(&act, '\0', sizeof(act));
act.sa_sigaction = &signal_callback_handler;
act.sa_flags = SA_SIGINFO;
sigaction(SIGTERM, &act, NULL);
skeleton_daemon();
_init_mutex();
mStatus = 1;
getTASInfo();
if (initThread() == EXIT_FAILURE)
exit(EXIT_FAILURE);
return EXIT_SUCCESS;
}
void skeleton_daemon() {
pid_t pid;
pid = fork();
if (pid < 0) {
printf("fork failed!\n");
exit(EXIT_FAILURE);
}
//printf("file name %s\n", pidFile);
if (pid > 0) {
//printf("pid = %d\n", pid);
exit(EXIT_SUCCESS);
}
umask(0);
if (setsid() < 0) {
printf("set sid failed!\n");
exit(EXIT_FAILURE);
}
if (chdir("/") < 0) {
printf("change to root directory failed!\n");
exit(EXIT_FAILURE);
}
int x;
for (x = sysconf(_SC_OPEN_MAX); x > 0; x--) {
close(x);
}
}
int initThread() {
int err;
if (pthread_mutex_init(&monitor_lock, NULL) != 0) {
printf("\n mutex init failed\n");
printErrLog("initThread ", "monitor mutex init failed");
return(EXIT_FAILURE);
}
if (pthread_cond_init(&monitor_condition, NULL) != 0) {
printf("\n condition init failed\n");
printErrLog("initThread ", "monitor condition init failed");
return(EXIT_FAILURE);
}
err = pthread_create(&monitor_thread, NULL, (void *)&monitor_handler, NULL);
if (err != 0) {
printErrLog("pthread_create ", " monitor thread create failed");
return(EXIT_FAILURE);
}
closelog();
pthread_join(monitor_thread, NULL);
return(EXIT_SUCCESS);
}
int initIni() {
config_init(&cfg);
/* Read the file. If there is an error, report it and exit. */
if (!config_read_file(&cfg, ini_file)) {
root = config_root_setting(&cfg);
/* Add some settings to the configuration. */
group = config_setting_add(root, PATH_SEC, CONFIG_TYPE_GROUP);
setting = config_setting_add(group, INSTALLED_PATH_KEY, CONFIG_TYPE_STRING);
config_setting_set_string(setting, installed_path);
setting = config_setting_add(group, LOG_PATH_KEY, CONFIG_TYPE_STRING);
config_setting_set_string(setting, log_file);
setting = config_setting_add(group, ERR_LOG_PATH_KEY, CONFIG_TYPE_STRING);
config_setting_set_string(setting, err_log_file);
setting = config_setting_add(group, COMMAND_LOG_PATH_KEY, CONFIG_TYPE_STRING);
config_setting_set_string(setting, command_log_file);
group = config_setting_add(root, CONFIG_SEC, CONFIG_TYPE_GROUP);
setting = config_setting_add(group, UPDATE_FREQ_KEY, CONFIG_TYPE_INT);
config_setting_set_int(setting, DEFAULT_FREQ);
/* Write out the new configuration. */
if (!config_write_file(&cfg, ini_file))
{
fprintf(stderr, "Error while writing file.\n");
printErrLog("initIni ", "Error while writing file");
config_destroy(&cfg);
return(EXIT_FAILURE);
}
}
else {
config_setting_t *s = config_lookup(&cfg, CONFIG_SEC);
config_setting_lookup_int(s, UPDATE_FREQ_KEY, &updateSec);
}
if (updateSec < MIN_FREQ)
updateSec = MIN_FREQ;
else if (updateSec > MAX_FREQ)
updateSec = MAX_FREQ;
config_destroy(&cfg);
return(EXIT_SUCCESS);
}
void printLog(BYTE * title, BYTE * value) {
FILE *fp = NULL;
fp = fopen(log_file, "a+");
fprintf(fp, "%s %s\n", title, value);
fflush(fp);
fclose(fp);
}
void printIntLog(BYTE * title, int value) {
FILE *fp = NULL;
fp = fopen(log_file, "a+");
fprintf(fp, "%s %d\n", title, value);
fflush(fp);
fclose(fp);
}
void getStartTime() {
FILE *fp = NULL;
fp = fopen(time_file, "r");
memset(mTimeStamp, '\0', sizeof(mTimeStamp));
fgets(mTimeStamp, 5, fp);
fclose(fp);
}
int getTASInfo() {
BYTE *information = NULL;
BYTE *information2 = NULL;
asprintf(&information, "%s%s%s%s%s%s%d%s%s%s", VERSION, ";", BUILD, ";", PROTOCOL_VERSION, ";",
mStatus, ";", mTimeStamp, ";");
asprintf(&information2, "%s%s%s%s%s%s%d%s%x%x%x%x%s", VERSION, ";", BUILD, ";", PROTOCOL_VERSION, ";",
mStatus, ";", mTimeStamp[0], mTimeStamp[1], mTimeStamp[2], mTimeStamp[3],";");
printLog("TAS info ->", information2);
return 0;
}
int getOSName() {
FILE *fp = NULL;
BYTE buffer[BUFFER_SIZE];
BYTE *tmp = NULL;
TRY {
if ((fp = popen("uname", "r")) == NULL) {
THROW (CMD_NOT_FND);
}
else {
if (fgets(buffer, sizeof(buffer), fp) == NULL)
THROW (CMD_NOT_FND);
}
}
CATCH (CMD_NOT_FND) {
buffer[0] = 'n';
buffer[1] = '/';
buffer[2] = 'a';
buffer[3] = '\0';
printErrLog("OS name ->", "command not found");
}
FINALLY {
pclose(fp);
//printf("OS name length %d\n", strlen(buffer));
}
ETRY;
tmp = strrchr(buffer, '\n');
if (tmp)
*tmp = ';';
printf("OS name : %s\n", buffer);
printLog("OS name ->", buffer);
return 0;
}
void signal_callback_handler(int signum, siginfo_t *siginfo, void *context) {
if (signum == SIGTERM) {
clearData();
}
exit(signum);
}
void monitor_handler(void *arg) {
static_flag = 1;
struct timespec outtime;
struct timeval now;
int ret = 0;
pthread_mutex_lock(&monitor_lock);
while (!getStopFlag()) {
getOSName();
gettimeofday(&now, NULL);
outtime.tv_sec = now.tv_sec + updateSec;
outtime.tv_nsec = now.tv_usec * 1000;
ret = pthread_cond_timedwait(&monitor_condition, &monitor_lock, &outtime);
}
pthread_mutex_unlock(&monitor_lock);
pthread_exit(0);
}
答案 0 :(得分:0)
我找到了解决方案
for (x = sysconf(_SC_OPEN_MAX); x > 0; x--) {
close(x);
}
上面的代码是系统出错的地方,它不能在FreeBSD中使用。 你需要把它写成如下所示
/* close all descriptors */
for (i = getdtablesize(); i >= 0; --i)
{
close(i);
}
/* Route I/O connections */
/* Open STDIN */
i = open("/dev/null", O_RDWR);
/* STDOUT */
dup(i);
/* STDERR */
dup(i);