git: 5f89aea7b74a - main - ctld: fix several process setup/teardown bugs
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 19 Sep 2024 01:27:46 UTC
The branch main has been updated by asomers:
URL: https://cgit.FreeBSD.org/src/commit/?id=5f89aea7b74aa4605b25af62e31303097a4a48cc
commit 5f89aea7b74aa4605b25af62e31303097a4a48cc
Author: Alan Somers <asomers@FreeBSD.org>
AuthorDate: 2024-08-07 15:21:08 +0000
Commit: Alan Somers <asomers@FreeBSD.org>
CommitDate: 2024-09-18 20:06:31 +0000
ctld: fix several process setup/teardown bugs
All of the below bugs could result in a system where ctld is not
running, but LUNs and targets still exist in the kernel; a difficult
situation to recover from.
* open the pidfile earlier. Open the pidfile before reading the
kernel's current state, so two racing ctld processes won't step on
each others' toes.
* close the pidfile later. Close it after tearing down the
configuration, for the same reason.
* If the configured pidfile changes, then rename it on SIGHUP rather
than remove and recreate it.
* When running in debug mode, don't close the pidfile while handling a
new connection. Only do that in non-debug mode, in the child of the
fork.
* Register signal handlers earlier. Otherwise a SIGTERM signal received
during startup could kill ctld without tearing down the configuration.
MFC after: 2 weeks
PR: 271460
Sponsored by: Axcient
Reviewed by: mav
Pull Request: https://github.com/freebsd/freebsd-src/pull/1370
---
usr.sbin/ctld/ctld.c | 70 ++++++++++++++++++++++++++++++----------------------
1 file changed, 40 insertions(+), 30 deletions(-)
diff --git a/usr.sbin/ctld/ctld.c b/usr.sbin/ctld/ctld.c
index 805648f0465f..346d1908aa6f 100644
--- a/usr.sbin/ctld/ctld.c
+++ b/usr.sbin/ctld/ctld.c
@@ -1915,7 +1915,6 @@ conf_apply(struct conf *oldconf, struct conf *newconf)
struct portal *oldp, *newp;
struct port *oldport, *newport, *tmpport;
struct isns *oldns, *newns;
- pid_t otherpid;
int changed, cumulated_error = 0, error, sockbuf;
int one = 1;
@@ -1924,32 +1923,25 @@ conf_apply(struct conf *oldconf, struct conf *newconf)
log_init(newconf->conf_debug);
}
- if (oldconf->conf_pidfh != NULL) {
- assert(oldconf->conf_pidfile_path != NULL);
- if (newconf->conf_pidfile_path != NULL &&
- strcmp(oldconf->conf_pidfile_path,
- newconf->conf_pidfile_path) == 0) {
- newconf->conf_pidfh = oldconf->conf_pidfh;
- oldconf->conf_pidfh = NULL;
- } else {
- log_debugx("removing pidfile %s",
- oldconf->conf_pidfile_path);
- pidfile_remove(oldconf->conf_pidfh);
- oldconf->conf_pidfh = NULL;
- }
- }
-
- if (newconf->conf_pidfh == NULL && newconf->conf_pidfile_path != NULL) {
- log_debugx("opening pidfile %s", newconf->conf_pidfile_path);
- newconf->conf_pidfh =
- pidfile_open(newconf->conf_pidfile_path, 0600, &otherpid);
- if (newconf->conf_pidfh == NULL) {
- if (errno == EEXIST)
- log_errx(1, "daemon already running, pid: %jd.",
- (intmax_t)otherpid);
- log_err(1, "cannot open or create pidfile \"%s\"",
- newconf->conf_pidfile_path);
+ if (oldconf->conf_pidfile_path != NULL &&
+ newconf->conf_pidfile_path != NULL)
+ {
+ if (strcmp(oldconf->conf_pidfile_path,
+ newconf->conf_pidfile_path) != 0)
+ {
+ /* pidfile has changed. rename it */
+ log_debugx("moving pidfile to %s",
+ newconf->conf_pidfile_path);
+ if (rename(oldconf->conf_pidfile_path,
+ newconf->conf_pidfile_path))
+ {
+ log_err(1, "renaming pidfile %s -> %s",
+ oldconf->conf_pidfile_path,
+ newconf->conf_pidfile_path);
+ }
}
+ newconf->conf_pidfh = oldconf->conf_pidfh;
+ oldconf->conf_pidfh = NULL;
}
/*
@@ -2471,8 +2463,8 @@ handle_connection(struct portal *portal, int fd,
close(fd);
return;
}
+ pidfile_close(conf->conf_pidfh);
}
- pidfile_close(conf->conf_pidfh);
error = getnameinfo(client_sa, client_sa->sa_len,
host, sizeof(host), NULL, 0, NI_NUMERICHOST);
@@ -2807,6 +2799,7 @@ main(int argc, char **argv)
struct isns *newns;
const char *config_path = DEFAULT_CONFIG_PATH;
int debug = 0, ch, error;
+ pid_t otherpid;
bool dont_daemonize = false;
bool test_config = false;
bool use_ucl = false;
@@ -2846,7 +2839,6 @@ main(int argc, char **argv)
kernel_init();
TAILQ_INIT(&kports.pports);
- oldconf = conf_new_from_kernel(&kports);
newconf = conf_new_from_file(config_path, use_ucl);
if (newconf == NULL)
@@ -2855,6 +2847,22 @@ main(int argc, char **argv)
if (test_config)
return (0);
+ assert(newconf->conf_pidfile_path != NULL);
+ log_debugx("opening pidfile %s", newconf->conf_pidfile_path);
+ newconf->conf_pidfh = pidfile_open(newconf->conf_pidfile_path, 0600,
+ &otherpid);
+ if (newconf->conf_pidfh == NULL) {
+ if (errno == EEXIST)
+ log_errx(1, "daemon already running, pid: %jd.",
+ (intmax_t)otherpid);
+ log_err(1, "cannot open or create pidfile \"%s\"",
+ newconf->conf_pidfile_path);
+ }
+
+ register_signals();
+
+ oldconf = conf_new_from_kernel(&kports);
+
if (debug > 0) {
oldconf->conf_debug = debug;
newconf->conf_debug = debug;
@@ -2870,8 +2878,6 @@ main(int argc, char **argv)
conf_delete(oldconf);
oldconf = NULL;
- register_signals();
-
if (dont_daemonize == false) {
log_debugx("daemonizing");
if (daemon(0, 0) == -1) {
@@ -2926,6 +2932,10 @@ main(int argc, char **argv)
error = conf_apply(oldconf, newconf);
if (error != 0)
log_warnx("failed to apply configuration");
+ if (oldconf->conf_pidfh) {
+ pidfile_remove(oldconf->conf_pidfh);
+ oldconf->conf_pidfh = NULL;
+ }
conf_delete(newconf);
conf_delete(oldconf);
oldconf = NULL;