Introduce sd_notify_barrier
This adds the sd_notify_barrier function, to allow users to synchronize against the reception of sd_notify(3) status messages. It acts as a synchronization point, and a successful return gurantees that all previous messages have been consumed by the manager. This can be used to eliminate race conditions where the sending process exits too early for systemd to associate its PID to a cgroup and attribute the status message to a unit correctly. systemd-notify now uses this function for proper notification delivery and be useful for NotifyAccess=all units again in user mode, or in cases where it doesn't have a control process as parent. Fixes: #2739
This commit is contained in:
@@ -18,6 +18,7 @@
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
#include "terminal-util.h"
|
||||
#include "time-util.h"
|
||||
#include "user-util.h"
|
||||
#include "util.h"
|
||||
|
||||
@@ -27,6 +28,7 @@ static const char *arg_status = NULL;
|
||||
static bool arg_booted = false;
|
||||
static uid_t arg_uid = UID_INVALID;
|
||||
static gid_t arg_gid = GID_INVALID;
|
||||
static bool arg_no_block = false;
|
||||
|
||||
static int help(void) {
|
||||
_cleanup_free_ char *link = NULL;
|
||||
@@ -45,6 +47,7 @@ static int help(void) {
|
||||
" --uid=USER Set user to send from\n"
|
||||
" --status=TEXT Set status text\n"
|
||||
" --booted Check if the system was booted up with systemd\n"
|
||||
" --no-block Do not wait until operation finished\n"
|
||||
"\nSee the %s for details.\n"
|
||||
, program_invocation_short_name
|
||||
, ansi_highlight(), ansi_normal()
|
||||
@@ -83,6 +86,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
ARG_STATUS,
|
||||
ARG_BOOTED,
|
||||
ARG_UID,
|
||||
ARG_NO_BLOCK
|
||||
};
|
||||
|
||||
static const struct option options[] = {
|
||||
@@ -93,6 +97,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
{ "status", required_argument, NULL, ARG_STATUS },
|
||||
{ "booted", no_argument, NULL, ARG_BOOTED },
|
||||
{ "uid", required_argument, NULL, ARG_UID },
|
||||
{ "no-block", no_argument, NULL, ARG_NO_BLOCK },
|
||||
{}
|
||||
};
|
||||
|
||||
@@ -157,6 +162,10 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
break;
|
||||
}
|
||||
|
||||
case ARG_NO_BLOCK:
|
||||
arg_no_block = true;
|
||||
break;
|
||||
|
||||
case '?':
|
||||
return -EINVAL;
|
||||
|
||||
@@ -256,6 +265,16 @@ static int run(int argc, char* argv[]) {
|
||||
if (r == 0)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
|
||||
"No status data could be sent: $NOTIFY_SOCKET was not set");
|
||||
|
||||
if (!arg_no_block) {
|
||||
r = sd_notify_barrier(0, 5 * USEC_PER_SEC);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to invoke barrier: %m");
|
||||
if (r == 0)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
|
||||
"No status data could be sent: $NOTIFY_SOCKET was not set");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user