aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJuraj Lutter <otis@FreeBSD.org>2024-04-25 13:40:00 +0000
committerJuraj Lutter <otis@FreeBSD.org>2024-05-22 07:45:23 +0000
commit7618c9e1637caea97723ff8accd60f3dc436b044 (patch)
treed214988cb39cdc1ba7c5644e7503e6c667e91036
parentbdd12889eaa64032b3d09ef47e9a6f7081863378 (diff)
daemon: Add -C (--restart-count) option
Add a new option (-C, --restart-count) to specify the maximum number of times that the controlled process is restarted if restart (-r) is restarted. Reviewed by: kevans Differential Revision: https://reviews.freebsd.org/D44944
-rw-r--r--usr.sbin/daemon/daemon.819
-rw-r--r--usr.sbin/daemon/daemon.c25
2 files changed, 40 insertions, 4 deletions
diff --git a/usr.sbin/daemon/daemon.8 b/usr.sbin/daemon/daemon.8
index 4fafb8528f18..52fbc230ac77 100644
--- a/usr.sbin/daemon/daemon.8
+++ b/usr.sbin/daemon/daemon.8
@@ -24,7 +24,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd December 27, 2023
+.Dd April 25, 2024
.Dt DAEMON 8
.Os
.Sh NAME
@@ -43,6 +43,7 @@
.Op Fl T Ar syslog_tag
.Op Fl l Ar syslog_facility
.Op Fl R Ar restart_delay_seconds
+.Op Fl C Ar restart_count
.Ar command arguments ...
.Sh DESCRIPTION
The
@@ -55,6 +56,17 @@ log file.
.Pp
The options are as follows:
.Bl -tag -width indent
+.It Fl C , Fl -restart-count Ar restart_count
+Restart the process at most
+.Ar restart_count
+times.
+When zero is specified,
+.Nm
+will exit.
+The maximum restart count is
+.Cm 128 .
+This option is used together with option
+.Fl -restart .
.It Fl c , Fl -change-dir
Change the current working directory to the root
.Pq Dq Pa / .
@@ -72,8 +84,9 @@ Close
and re-open it when signal
.Dv SIGHUP
is received, for interoperability with
-.Xr newsyslog 1
-and similar log rotation / archival mechanisms. If
+.Xr newsyslog 8
+and similar log rotation / archival mechanisms.
+If
.Fl -output-file
is not specified, this flag is ignored.
.It Fl l , Fl -syslog-facility Ar syslog_facility
diff --git a/usr.sbin/daemon/daemon.c b/usr.sbin/daemon/daemon.c
index 26e34d1d2e2b..7214faf8bde3 100644
--- a/usr.sbin/daemon/daemon.c
+++ b/usr.sbin/daemon/daemon.c
@@ -56,6 +56,9 @@
/* 1 year in seconds */
#define MAX_RESTART_DELAY 60*60*24*365
+/* Maximum number of restarts */
+#define MAX_RESTART_COUNT 128
+
#define LBUF_SIZE 4096
enum daemon_mode {
@@ -92,6 +95,8 @@ struct daemon_state {
bool restart_enabled;
bool syslog_enabled;
bool log_reopen;
+ int restart_count;
+ int restarted_count;
};
static void restrict_process(const char *);
@@ -109,7 +114,7 @@ static void daemon_exec(struct daemon_state *);
static bool daemon_is_child_dead(struct daemon_state *);
static void daemon_set_child_pipe(struct daemon_state *);
-static const char shortopts[] = "+cfHSp:P:ru:o:s:l:t:m:R:T:h";
+static const char shortopts[] = "+cfHSp:P:ru:o:s:l:t:m:R:T:C:h";
static const struct option longopts[] = {
{ "change-dir", no_argument, NULL, 'c' },
@@ -121,6 +126,7 @@ static const struct option longopts[] = {
{ "child-pidfile", required_argument, NULL, 'p' },
{ "supervisor-pidfile", required_argument, NULL, 'P' },
{ "restart", no_argument, NULL, 'r' },
+ { "restart-count", required_argument, NULL, 'C' },
{ "restart-delay", required_argument, NULL, 'R' },
{ "title", required_argument, NULL, 't' },
{ "user", required_argument, NULL, 'u' },
@@ -139,6 +145,7 @@ usage(int exitcode)
" [-u user] [-o output_file] [-t title]\n"
" [-l syslog_facility] [-s syslog_priority]\n"
" [-T syslog_tag] [-m output_mask] [-R restart_delay_secs]\n"
+ " [-C restart_count]\n"
"command arguments ...\n");
(void)fprintf(stderr,
@@ -152,6 +159,7 @@ usage(int exitcode)
" --child-pidfile -p <file> Write PID of the child process to file\n"
" --supervisor-pidfile -P <file> Write PID of the supervisor process to file\n"
" --restart -r Restart child if it terminates (1 sec delay)\n"
+ " --restart-count -C <N> Restart child at most N times, then exit\n"
" --restart-delay -R <N> Restart child if it terminates after N sec\n"
" --title -t <title> Set the title of the supervisor process\n"
" --user -u <user> Drop privileges, run as given user\n"
@@ -198,6 +206,13 @@ main(int argc, char *argv[])
case 'c':
state.keep_cur_workdir = 0;
break;
+ case 'C':
+ state.restart_count = (int)strtonum(optarg, 0,
+ MAX_RESTART_COUNT, &e);
+ if (e != NULL) {
+ errx(6, "invalid restart count: %s", e);
+ }
+ break;
case 'f':
state.keep_fds_open = 0;
break;
@@ -331,6 +346,12 @@ main(int argc, char *argv[])
state.mode = MODE_SUPERVISE;
daemon_eventloop(&state);
daemon_sleep(&state);
+ if (state.restart_enabled && state.restart_count > -1) {
+ if (state.restarted_count >= state.restart_count) {
+ state.restart_enabled = false;
+ }
+ state.restarted_count++;
+ }
} while (state.restart_enabled);
daemon_terminate(&state);
@@ -723,6 +744,8 @@ daemon_state_init(struct daemon_state *state)
.keep_fds_open = 1,
.output_fd = -1,
.output_filename = NULL,
+ .restart_count = -1,
+ .restarted_count = 0
};
}