Преглед изворни кода

smartdns: fix startup issue.

Nick Peng пре 5 дана
родитељ
комит
f73d656994
2 измењених фајлова са 52 додато и 10 уклоњено
  1. 0 8
      src/main.c
  2. 52 2
      src/smartdns.c

+ 0 - 8
src/main.c

@@ -23,13 +23,5 @@
 
 int main(int argc, char *argv[])
 {
-	const char *smartdns_workdir = getenv("SMARTDNS_WORKDIR");
-	if (smartdns_workdir != NULL) {
-		if (chdir(smartdns_workdir) != 0) {
-			fprintf(stderr, "chdir to %s failed: %s\n", smartdns_workdir, strerror(errno));
-			return 1;
-		}
-	}
-
 	return smartdns_main(argc, argv);
 }

+ 52 - 2
src/smartdns.c

@@ -1001,17 +1001,53 @@ void smartdns_restart(void)
 	dns_server_stop();
 }
 
+static const char *smartdns_exec_dir(void)
+{
+	static char start_dir[PATH_MAX] = {0};
+	if (start_dir[0] == 0) {
+		if (getcwd(start_dir, sizeof(start_dir)) == NULL) {
+			snprintf(start_dir, sizeof(start_dir), ".");
+		}
+	}
+	return start_dir;
+}
+
 static int smartdns_enter_monitor_mode(int argc, char *argv[], int no_deamon)
 {
+	char exec_path[PATH_MAX] = {0};
+
 	setenv("SMARTDNS_RESTART_ON_CRASH", "1", 1);
 	if (no_deamon == 1) {
 		setenv("SMARTDNS_NO_DAEMON", "1", 1);
 	}
-	execv(argv[0], argv);
-	tlog(TLOG_ERROR, "execv failed, %s", strerror(errno));
+
+	chdir(smartdns_exec_dir());
+	if (readlink("/proc/self/exe", exec_path, sizeof(exec_path) - 1) > 0) {
+		execv(exec_path, argv);
+	} else {
+		safe_strncpy(exec_path, argv[0], sizeof(exec_path));
+		execvp(exec_path, argv);
+	}
+
+	tlog(TLOG_ERROR, "execv failed, %s, %s", exec_path, strerror(errno));
 	return -1;
 }
 
+static int smartdns_init_workdir(void)
+{
+	smartdns_exec_dir();
+	const char *smartdns_workdir = getenv("SMARTDNS_WORKDIR");
+
+	if (smartdns_workdir != NULL) {
+		if (chdir(smartdns_workdir) != 0) {
+			fprintf(stderr, "chdir to %s failed: %s\n", smartdns_workdir, strerror(errno));
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
 #ifdef TEST
 
 static smartdns_post_func _smartdns_post = NULL;
@@ -1066,6 +1102,10 @@ int smartdns_main(int argc, char *argv[])
 										   {"help", no_argument, NULL, 'h'},
 										   {NULL, 0, NULL, 0}};
 
+	if (smartdns_init_workdir() != 0) {
+		return 1;
+	}
+
 	safe_strncpy(config_file, SMARTDNS_CONF_FILE, MAX_LINE_LEN);
 
 	if (stat("/run", &sb) == 0 && S_ISDIR(sb.st_mode)) {
@@ -1145,6 +1185,11 @@ int smartdns_main(int argc, char *argv[])
 		unsetenv("SMARTDNS_NO_DAEMON");
 	}
 
+	/* started by systemd, do not restart when crash */
+	if (getenv("INVOCATION_ID") != NULL) {
+		restart_when_crash = 0;
+	}
+
 	smartdns_run_monitor_ret init_ret = _smartdns_run_monitor(restart_when_crash, is_run_as_daemon);
 	if (init_ret != SMARTDNS_RUN_MONITOR_OK) {
 		if (init_ret == SMARTDNS_RUN_MONITOR_EXIT) {
@@ -1164,6 +1209,11 @@ int smartdns_main(int argc, char *argv[])
 		goto errout;
 	}
 
+	/* started by systemd, do not restart when crash */
+	if (getenv("INVOCATION_ID") != NULL) {
+		dns_conf.dns_restart_on_crash = 0;
+	}
+
 	if (dns_conf.dns_restart_on_crash && restart_when_crash == 0) {
 		return smartdns_enter_monitor_mode(argc, argv, dns_conf.dns_no_daemon || !is_run_as_daemon);
 	}