Skip to content

Commit

Permalink
Merge pull request #1300 from jimklimov/issue-1299
Browse files Browse the repository at this point in the history
  • Loading branch information
jimklimov committed Feb 17, 2022
2 parents 78a3dbb + aae4fe6 commit 516d195
Show file tree
Hide file tree
Showing 12 changed files with 266 additions and 48 deletions.
60 changes: 54 additions & 6 deletions clients/upsmon.c
Original file line number Diff line number Diff line change
Expand Up @@ -1279,7 +1279,7 @@ static int parse_conf_arg(size_t numargs, char **arg)
}

/* RUN_AS_USER <userid> */
if (!strcmp(arg[0], "RUN_AS_USER")) {
if (!strcmp(arg[0], "RUN_AS_USER")) {
free(run_as_user);
run_as_user = xstrdup(arg[1]);
return 1;
Expand Down Expand Up @@ -1393,6 +1393,13 @@ static void loadconfig(void)
fatalx(EXIT_FAILURE, "%s", ctx.errmsg);
}

if (reload_flag == 1) {
/* if upsmon.conf added or changed
* (or commented away) the debug_min
* setting, detect that */
nut_debug_level_global = -1;
}

while (pconf_file_next(&ctx)) {
if (pconf_parse_error(&ctx)) {
upslogx(LOG_ERR, "Parse error: %s:%d: %s",
Expand All @@ -1419,6 +1426,15 @@ static void loadconfig(void)
}
}

if (reload_flag == 1) {
if (nut_debug_level_global > -1) {
upslogx(LOG_INFO,
"Applying debug_min=%d from upsmon.conf",
nut_debug_level_global);
nut_debug_level = nut_debug_level_global;
}
}

pconf_finish(&ctx);
}

Expand Down Expand Up @@ -1809,6 +1825,7 @@ static void help(const char *arg_progname)
printf(" - fsd: shutdown all primary-mode UPSes (use with caution)\n");
printf(" - reload: reread configuration\n");
printf(" - stop: stop monitoring and exit\n");
printf(" -P <pid> send the signal above to specified PID (bypassing PID file)\n");
printf(" -D raise debugging level (and stay foreground by default)\n");
printf(" -F stay foregrounded even if no debugging is enabled\n");
printf(" -B stay backgrounded even if debugging is bumped\n");
Expand Down Expand Up @@ -2042,7 +2059,8 @@ static void check_parent(void)
int main(int argc, char *argv[])
{
const char *prog = xbasename(argv[0]);
int i, cmd = 0, checking_flag = 0, foreground = -1;
int i, cmd = 0, cmdret = -1, checking_flag = 0, foreground = -1;
pid_t oldpid = -1;

printf("Network UPS Tools %s %s\n", prog, UPS_VERSION);

Expand All @@ -2053,7 +2071,7 @@ int main(int argc, char *argv[])

run_as_user = xstrdup(RUN_AS_USER);

while ((i = getopt(argc, argv, "+DFBhic:f:pu:VK46")) != -1) {
while ((i = getopt(argc, argv, "+DFBhic:P:f:pu:VK46")) != -1) {
switch (i) {
case 'c':
if (!strncmp(optarg, "fsd", strlen(optarg)))
Expand All @@ -2067,6 +2085,12 @@ int main(int argc, char *argv[])
if (cmd == 0)
help(argv[0]);
break;

case 'P':
if ((oldpid = parsepid(optarg)) < 0)
help(argv[0]);
break;

case 'D':
nut_debug_level++;
break;
Expand Down Expand Up @@ -2121,17 +2145,41 @@ int main(int argc, char *argv[])
}

if (cmd) {
sendsignal(prog, cmd);
exit(EXIT_SUCCESS);
if (oldpid < 0) {
cmdret = sendsignal(prog, cmd);
} else {
cmdret = sendsignalpid(oldpid, cmd);
}
/* exit(EXIT_SUCCESS); */
exit((cmdret == 0)?EXIT_SUCCESS:EXIT_FAILURE);
}

/* otherwise, we are being asked to start.
* so check if a previous instance is running by sending signal '0'
* (Ie 'kill <pid> 0') */
if (sendsignal(prog, 0) == 0) {
if (oldpid < 0) {
cmdret = sendsignal(prog, 0);
} else {
cmdret = sendsignalpid(oldpid, 0);
}
switch (cmdret) {
case 0:
printf("Fatal error: A previous upsmon instance is already running!\n");
printf("Either stop the previous instance first, or use the 'reload' command.\n");
exit(EXIT_FAILURE);

case -3:
case -2:
upslogx(LOG_WARNING, "Could not %s PID file "
"to see if previous upsmon instance is "
"already running!\n",
(cmdret == -3 ? "find" : "parse"));
break;

case -1:
default:
/* Just failed to send signal, no competitor running */
break;
}

argc -= optind;
Expand Down
106 changes: 72 additions & 34 deletions common/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,9 @@ void writepid(const char *name)
pidf = fopen(fn, "w");

if (pidf) {
fprintf(pidf, "%d\n", (int) getpid());
intmax_t pid = (intmax_t)getpid();
upsdebugx(1, "Saving PID %jd into %s", pid, fn);
fprintf(pidf, "%jd\n", pid);
fclose(pidf);
} else {
upslog_with_errno(LOG_NOTICE, "writepid: fopen %s", fn);
Expand All @@ -302,61 +304,97 @@ void writepid(const char *name)
umask(mask);
}

/* open pidfn, get the pid, then send it sig */
int sendsignalfn(const char *pidfn, int sig)
/* send sig to pid, returns -1 for error, or
* zero for a successfully sent signal
*/
int sendsignalpid(pid_t pid, int sig)
{
char buf[SMALLBUF];
FILE *pidf;
pid_t pid = -1;
int ret;

pidf = fopen(pidfn, "r");
if (!pidf) {
upslog_with_errno(LOG_NOTICE, "fopen %s", pidfn);
if (pid < 2 || pid > get_max_pid_t()) {
upslogx(LOG_NOTICE,
"Ignoring invalid pid number %" PRIdMAX,
(intmax_t) pid);
return -1;
}

if (fgets(buf, sizeof(buf), pidf) == NULL) {
upslogx(LOG_NOTICE, "Failed to read pid from %s", pidfn);
fclose(pidf);
/* see if this is going to work first */
ret = kill(pid, 0);

if (ret < 0) {
perror("kill");
return -1;
}

{ /* scoping */
intmax_t _pid = strtol(buf, (char **)NULL, 10); /* assuming 10 digits for a long */
if (_pid <= get_max_pid_t()) {
pid = (pid_t)_pid;
} else {
upslogx(LOG_NOTICE, "Received a pid number too big for a pid_t: %" PRIdMAX, _pid);
if (sig != 0) {
/* now actually send it */
ret = kill(pid, sig);

if (ret < 0) {
perror("kill");
return -1;
}
}

if (pid < 2) {
upslogx(LOG_NOTICE, "Ignoring invalid pid number %" PRIdMAX, (intmax_t) pid);
fclose(pidf);
return -1;
return 0;
}

/* parses string buffer into a pid_t if it passes
* a few sanity checks; returns -1 on error
*/
pid_t parsepid(const char *buf)
{
pid_t pid = -1;

/* assuming 10 digits for a long */
intmax_t _pid = strtol(buf, (char **)NULL, 10);
if (_pid <= get_max_pid_t()) {
pid = (pid_t)_pid;
} else {
upslogx(LOG_NOTICE, "Received a pid number too big for a pid_t: %" PRIdMAX, _pid);
}

/* see if this is going to work first */
ret = kill(pid, 0);
return pid;
}

if (ret < 0) {
perror("kill");
/* open pidfn, get the pid, then send it sig
* returns negative codes for errors, or
* zero for a successfully sent signal
*/
int sendsignalfn(const char *pidfn, int sig)
{
char buf[SMALLBUF];
FILE *pidf;
pid_t pid = -1;
int ret = -1;

pidf = fopen(pidfn, "r");
if (!pidf) {
upslog_with_errno(LOG_NOTICE, "fopen %s", pidfn);
return -3;
}

if (fgets(buf, sizeof(buf), pidf) == NULL) {
upslogx(LOG_NOTICE, "Failed to read pid from %s", pidfn);
fclose(pidf);
return -1;
return -2;
}
/* TOTHINK: Original code only closed pidf before
* exiting the method, on error or "normally".
* Why not here? Do we want an (exclusive?) hold
* on it while being active in the method?
*/

/* now actually send it */
ret = kill(pid, sig);
/* this method actively reports errors, if any */
pid = parsepid(buf);

if (ret < 0) {
perror("kill");
fclose(pidf);
return -1;
if (pid >= 0) {
/* this method actively reports errors, if any */
ret = sendsignalpid(pid, sig);
}

fclose(pidf);
return 0;
return ret;
}

int snprintfcat(char *dst, size_t size, const char *fmt, ...)
Expand Down
11 changes: 11 additions & 0 deletions conf/upsd.conf.sample
Original file line number Diff line number Diff line change
Expand Up @@ -155,3 +155,14 @@
# running mode directly, and without need to edit init-scripts or service
# unit definitions. Note that command-line option `-D` can only increase
# this verbosity level.
#
# NOTE: if the running daemon receives a `reload` command, presence of the
# `DEBUG_MIN NUMBER` value in the configuration file can be used to tune
# debugging verbosity in the running service daemon (it is recommended to
# comment it away or set the minimum to explicit zero when done, to avoid
# huge journals and I/O system abuse). Keep in mind that for this run-time
# tuning, the `DEBUG_MIN` value *present* in *reloaded* configuration files
# is applied instantly and overrides any previously set value, from file
# or CLI options, regardless of older logging level being higher or lower
# than the newly found number; a missing (or commented away) value however
# does not change the previously active logging verbosity.
11 changes: 11 additions & 0 deletions conf/upsmon.conf.sample.in
Original file line number Diff line number Diff line change
Expand Up @@ -440,3 +440,14 @@ FINALDELAY 5
# running mode directly, and without need to edit init-scripts or service
# unit definitions. Note that command-line option `-D` can only increase
# this verbosity level.
#
# NOTE: if the running daemon receives a `reload` command, presence of the
# `DEBUG_MIN NUMBER` value in the configuration file can be used to tune
# debugging verbosity in the running service daemon (it is recommended to
# comment it away or set the minimum to explicit zero when done, to avoid
# huge journals and I/O system abuse). Keep in mind that for this run-time
# tuning, the `DEBUG_MIN` value *present* in *reloaded* configuration files
# is applied instantly and overrides any previously set value, from file
# or CLI options, regardless of older logging level being higher or lower
# than the newly found number; a missing (or commented away) value however
# does not change the previously active logging verbosity.
11 changes: 11 additions & 0 deletions docs/man/upsd.conf.txt
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,17 @@ Optionally specify a minimum debug level for `upsd` data daemon, e.g. for
troubleshooting a deployment, without impacting foreground or background
running mode directly. Command-line option `-D` can only increase this
verbosity level.
+
NOTE: if the running daemon receives a `reload` command, presence of the
`DEBUG_MIN NUMBER` value in the configuration file can be used to tune
debugging verbosity in the running service daemon (it is recommended to
comment it away or set the minimum to explicit zero when done, to avoid
huge journals and I/O system abuse). Keep in mind that for this run-time
tuning, the `DEBUG_MIN` value *present* in *reloaded* configuration files
is applied instantly and overrides any previously set value, from file
or CLI options, regardless of older logging level being higher or lower
than the newly found number; a missing (or commented away) value however
does not change the previously active logging verbosity.

SEE ALSO
--------
Expand Down
7 changes: 7 additions & 0 deletions docs/man/upsd.txt
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,20 @@ are:
*reload*;; reread configuration files
*stop*;; stop process and exit

*-P* 'pid'::
Send the command signal above using specified PID number, rather than
consulting the PID file. This can help define service units which
start `upsd` as a foreground process so it does not create a PID file.
See also `-FF` option as an alternative.

*-D*::
Raise the debugging level. upsd will run in the foreground by default,
and will print information on stdout about the monitoring process.
Use this option multiple times for more details.

*-F*::
upsd will run in the foreground, regardless of debugging settings.
Specify twice (`-FF` or `-F -F`) to save the PID file even in this mode.

*-B*::
upsd will run in the background, regardless of debugging settings.
Expand Down
11 changes: 11 additions & 0 deletions docs/man/upsmon.conf.txt
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,17 @@ Optionally specify a minimum debug level for `upsmon` daemon, e.g. for
troubleshooting a deployment, without impacting foreground or background
running mode directly. Command-line option `-D` can only increase this
verbosity level.
+
NOTE: if the running daemon receives a `reload` command, presence of the
`DEBUG_MIN NUMBER` value in the configuration file can be used to tune
debugging verbosity in the running service daemon (it is recommended to
comment it away or set the minimum to explicit zero when done, to avoid
huge journals and I/O system abuse). Keep in mind that for this run-time
tuning, the `DEBUG_MIN` value *present* in *reloaded* configuration files
is applied instantly and overrides any previously set value, from file
or CLI options, regardless of older logging level being higher or lower
than the newly found number; a missing (or commented away) value however
does not change the previously active logging verbosity.

SEE ALSO
--------
Expand Down
8 changes: 7 additions & 1 deletion docs/man/upsmon.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ SYNOPSIS

*upsmon* -h

*upsmon* -c 'command'
*upsmon* -c 'command' [-P 'pid']

*upsmon* [-D] [-F | -B] [-K] [-p] [-u 'user']

Expand Down Expand Up @@ -44,6 +44,12 @@ commands are:
*reload*;; reread linkman:upsmon.conf[5] configuration file. See
"reloading nuances" below if this doesn't work.

*-P* 'pid'::
Send the command signal above using specified PID number, rather than
consulting the PID file. This can help define service units which
start main `upsmon` as a foreground process so it does not have to
rely on a PID file.

*-D*::
Raise the debugging level. upsmon will run in the foreground by default,
and will print information on stdout about the monitoring process.
Expand Down

0 comments on commit 516d195

Please sign in to comment.