gpt4 book ai didi

c - 当进程仍在运行时如何重新启动处理

转载 作者:太空宇宙 更新时间:2023-11-04 11:14:26 24 4
gpt4 key购买 nike

情况是这样的。我正在调试代码来执行日志记录功能。当用户登录时,将创建 .part 格式的日志文件。该文件保存在主机本地。我不知道为什么将其命名为 .part。当用户完成 session 时,日志文件将仅重命名为 .username。除了本地日志文件,此代码还连接到服务器,该服务器还将保存日志文件。问题是日志记录仍在运行,但主机突然重启。重启可能是由来自 root 的命令、强制重启或硬件故障引起的。这会导致日志记录文件保留为 .part,服务器也会跟进。

那么,我的问题是:

如何让它在重启过程中进程被杀死或终止之前重命名文件?

我应该处理什么信号?

我认为这可能涉及竞争条件,有没有办法让我延迟重启?

我的方法

试图处理 SIGPWR、SIGSTOP、SIGTERM、SIGQUIT

创建一个 bash 脚本以在进程启动时进行重命名。

主要代码如下:

int main(int argc, char **argv)
{
int ch;
int NoFork = 0;
struct event_config *evconfig;
struct event *signal_event_int;
struct event *signal_event_quit;
struct event *signal_event_term;
struct event *signal_event_hup;
struct event *signal_event_chld;
struct event *signal_event_pwr;
struct event *signal_event_stop;

syspath_init_from_argv0(argv[0]);

load_config(); /* load config first, the command line parameters will override */
event_set_log_callback(my_event_log_cb);

evconfig = event_config_new();
if (event_config_require_features(evconfig, EV_FEATURE_FDS)!=0) {
log_error("event_config_require_features_failed");
}
while (!done) {
/* ignore HUP first, just in case someone send us a HUP
when we are reloading config, that will create a condition
that makes us exit, with HangUp */
sig_catch(SIGHUP,SIG_IGN);
base = event_base_new_with_config(evconfig);

local_listener = create_local_listener(base);

if (!local_listener) {
log_error("Could not create a local listener!");
return 1;
}
http_listener = create_http_listener();
if (!http_listener) {
log_error("Could not create a remote listener!");
return 1;
}
evhttp_set_cb(http_listener, "/mrexec", http_mrexec_cb, NULL);
if (options.accept_remote) {
evhttp_set_cb(http_listener, "/rlog", http_rlog_cb, NULL);
}
if (pidfile_create(ACTSLOGD_PIDFILE)==-1) {
log_error("pidfile_create:failed:%d:%s", errno, strerror(errno));
}
LIST_INIT(&clientlist);
if (options.log_remote) {
start_log_remote();
}

signal_event_int = evsignal_new(base, SIGINT, exit_cb, (void *)base);
event_add(signal_event_int, NULL);
signal_event_quit = evsignal_new(base, SIGQUIT, exit_cb, (void *)base);
event_add(signal_event_quit, NULL);
signal_event_term = evsignal_new(base, SIGTERM, exit_cb, (void *)base);
event_add(signal_event_term, NULL);
signal_event_hup = evsignal_new(base, SIGHUP, reload_config_cb, (void *)base);
event_add(signal_event_hup, NULL);
signal_event_chld = evsignal_new(base, SIGCHLD, sigchld_cb, (void *)base);
event_add(signal_event_chld, NULL);
signal_event_pwr = evsignal_new(base, SIGPWR, power_off_cb, (void *)base);
event_add(signal_event_pwr, NULL);
signal_event_stop = evsignal_new(base, SIGSTOP, power_off_cb, (void *)base);
event_add(signal_event_chld, NULL);

actslog_event_start(AGENT_ACTSLOGD);
actslog_event_start(AGENT_ESCALATED);
event_base_dispatch(base);
printf("finished dispatch\n");

evconnlistener_free(local_listener);

evhttp_free(http_listener);
http_listener = NULL;

event_free(signal_event_int);
event_free(signal_event_quit);
event_free(signal_event_term);
event_free(signal_event_hup);
event_free(signal_event_pwr);
event_free(signal_event_stop);

if (options.log_remote) {
end_log_remote();
}
event_base_free(base);
if (!done) {
load_config();
}
while (clientlist.lh_first != NULL) {
struct bufferevent *bev = clientlist.lh_first->bev;
bufferevent_free(bev);
LIST_REMOVE(clientlist.lh_first, clients);
}
}
if (rlog) {
rlog_close(rlog);
}
unlink(PATH_ACTSLOG);
pidfile_cleanup(ACTSLOGD_PIDFILE);

return 0;
}

这是信号处理程序

static void exit_cb(evutil_socket_t sig, short events, void *user_data)
{
struct event_base *base = user_data;
struct timeval delay = { 2, 0 };

actslog_event_stop(AGENT_ACTSLOGD);
actslog_event_stop(AGENT_ESCALATED);

done = 1; //when this is 1, there is a function that will connect to the server to tell that the logging is stopped.

/* need to give some delay for us to send out the stop message to Logger */

event_base_loopexit(base, &delay);
}

static void power_off_cb(evutil_socket_t sig, short events, void *user_data)
{
struct event_base *base = user_data;
struct timeval delay = { 5, 0 };
char logfile_partial[MAXPATHLEN];
char logfile_complete[MAXPATHLEN];
char id[1024];

done =1;

event_base_loopexit(base,&delay);

snprintf(logfile_partial, //the logfile_partial will be the one with .part file
sizeof(logfile_partial),
"%s/SHELL.%s.part", logpath2, id);

snprintf(logfile_complete, //the logfile_complete will be the complete without .part
sizeof(logfile_complete),
"%s/SHELL.%s", logpath2, id);

if (rename(logfile_partial, logfile_complete)!=0) {
if (errno==ENOENT) {
int tmp;
log_error("mastershell [%s] log is incomplete", logfile_complete);
tmp = creat(logfile_complete, LOG_FILE_MODE);
if (tmp==-1) {
log_error("creat:%s:failed:%d:%s!!\n", logfile_complete, errno, strerror(errno));
} else {
close(tmp);
}
} else {
log_error("rename:%s:%s:failed:%d:%s!!\n", logfile_partial, logfile_complete, errno, strerror(errno));
}
}

if (rlog) {
rlog_close(rlog);
}
unlink(PATH_ACTSLOG);
pidfile_cleanup(ACTSLOGD_PIDFILE);
}

我已经测试过在 exit_cb 函数中处理所有信号。还有 power_off_cb 函数中的所有信号。它们都不起作用。我在 CentOS 和 Ubuntu 上测试过。日志记录过程是一个 Upstart 过程。非常感谢任何意见或建议。

最佳答案

Here's the situation. I'm debugging a code to do a logging function. When the user log in, the log file will be create with .part format. This file is save locally inside the host. I do not know why it's name as .part. When the user finish their session, the log file will be rename as .username only. Beside the local log file, this code is also connected to a server where this server will also save the logging file. The problem is when the logging is still running, but the host suddenly reboot. The reboot might be caused by command from root

如果它是由来自 root 的命令引起的,您可以在/etc/init.d/中创建一个脚本来处理它。

, or a force reboot, or maybe a hardware fault. This causes the logging file to stay as .part and the server also follows.

您无法预测 future ,操作系统也是如此。如果重启是由电源或硬件故障引起的,则无法预测。

关于c - 当进程仍在运行时如何重新启动处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21668611/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com