Merge pull request #17231 from poettering/event-source-exit-on-failure

sd-event: add "exit-on-failure" feature for event source
This commit is contained in:
Lennart Poettering 2020-10-07 12:55:56 +02:00 committed by GitHub
commit 1378ac6989
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 291 additions and 56 deletions

View File

@ -564,6 +564,10 @@ manpages = [
'SD_EVENT_ONESHOT',
'sd_event_source_get_enabled'],
''],
['sd_event_source_set_exit_on_failure',
'3',
['sd_event_source_get_exit_on_failure'],
''],
['sd_event_source_set_floating', '3', ['sd_event_source_get_floating'], ''],
['sd_event_source_set_prepare', '3', [], ''],
['sd_event_source_set_priority',

View File

@ -150,11 +150,10 @@
<citerefentry
project='man-pages'><refentrytitle>pthread_sigmask</refentrytitle><manvolnum>3</manvolnum></citerefentry>).</para>
<para>If the second parameter of
<function>sd_event_add_child()</function> is passed as NULL no
reference to the event source object is returned. In this case the
event source is considered "floating", and will be destroyed
implicitly when the event loop itself is destroyed.</para>
<para>If the second parameter of <function>sd_event_add_child()</function> is passed as
<constant>NULL</constant> no reference to the event source object is returned. In this case the event
source is considered "floating", and will be destroyed implicitly when the event loop itself is
destroyed.</para>
<para>Note that the <parameter>handler</parameter> function is
invoked at a time where the child process is not reaped yet (and
@ -164,6 +163,12 @@
event sources are installed will not be reaped by the event loop
implementation.</para>
<para>If the <parameter>handler</parameter> parameter to <function>sd_event_add_child()</function> is
<constant>NULL</constant>, and the event source fires, this will be considered a request to exit the
event loop. In this case, the <parameter>userdata</parameter> parameter, cast to an integer, is passed as
the exit code parameter to
<citerefentry><refentrytitle>sd_event_exit</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
<para>If both a child process state change event source and a
<constant>SIGCHLD</constant> signal event source is installed in
the same event loop, the configured event source priorities decide

View File

@ -116,11 +116,17 @@
<constant>SD_EVENT_OFF</constant> with
<citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
<para>If the second parameter of these functions is passed as
NULL no reference to the event source object is returned. In this
case the event source is considered "floating", and will be
destroyed implicitly when the event loop itself is
destroyed.</para>
<para>If the second parameter of these functions is passed as <constant>NULL</constant> no reference to
the event source object is returned. In this case the event source is considered "floating", and will be
destroyed implicitly when the event loop itself is destroyed.</para>
<para>If the <parameter>handler</parameter> parameter to <function>sd_event_add_defer()</function> or
<function>sd_event_add_post()</function> is <constant>NULL</constant>, and the event source fires, this
will be considered a request to exit the event loop. In this case, the <parameter>userdata</parameter>
parameter, cast to an integer, is passed as the exit code parameter to
<citerefentry><refentrytitle>sd_event_exit</refentrytitle><manvolnum>3</manvolnum></citerefentry>. Similar
functionality is not available for <function>sd_event_add_exit()</function>, as these types of event
sources are only dispatched when exiting anyway.</para>
</refsect1>
<refsect1>

View File

@ -95,9 +95,16 @@
it with
<citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
<para>If the second parameter of <function>sd_event_add_inotify()</function> is passed as NULL no reference to the
event source object is returned. In this case the event source is considered "floating", and will be destroyed
implicitly when the event loop itself is destroyed.</para>
<para>If the second parameter of <function>sd_event_add_inotify()</function> is passed as
<constant>NULL</constant> no reference to the event source object is returned. In this case the event
source is considered "floating", and will be destroyed implicitly when the event loop itself is
destroyed.</para>
<para>If the <parameter>handler</parameter> parameter to <function>sd_event_add_inotify()</function> is
<constant>NULL</constant>, and the event source fires, this will be considered a request to exit the
event loop. In this case, the <parameter>userdata</parameter> parameter, cast to an integer, is passed as
the exit code parameter to
<citerefentry><refentrytitle>sd_event_exit</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
<para><function>sd_event_source_get_inotify_mask()</function> retrieves the configured inotify watch mask of an
event source created previously with <function>sd_event_add_inotify()</function>. It takes the event source object

View File

@ -161,6 +161,12 @@
"floating", and will be destroyed implicitly when the event loop
itself is destroyed.</para>
<para>If the <parameter>handler</parameter> to <function>sd_event_add_io()</function> is
<constant>NULL</constant>, and the event source fires, this will be considered a request to exit the
event loop. In this case, the <parameter>userdata</parameter> parameter, cast to an integer, is passed as
the exit code parameter to
<citerefentry><refentrytitle>sd_event_exit</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
<para>Note that this call does not take possession of the file descriptor passed in, ownership (and thus
the duty to close it when it is no longer needed) remains with the caller. However, with the
<function>sd_event_source_set_io_fd_own()</function> call (see below) the event source may optionally

View File

@ -79,9 +79,7 @@
threads before this function is called (using <citerefentry
project='man-pages'><refentrytitle>sigprocmask</refentrytitle><manvolnum>2</manvolnum></citerefentry> or
<citerefentry
project='man-pages'><refentrytitle>pthread_sigmask</refentrytitle><manvolnum>3</manvolnum></citerefentry>). If
the handler is not specified (<parameter>handler</parameter> is <constant>NULL</constant>), a default
handler which causes the program to exit cleanly will be used.</para>
project='man-pages'><refentrytitle>pthread_sigmask</refentrytitle><manvolnum>3</manvolnum></citerefentry>).</para>
<para>By default, the event source is enabled permanently
(<constant>SD_EVENT_ON</constant>), but this may be changed with
@ -107,6 +105,12 @@
"floating", and will be destroyed implicitly when the event loop
itself is destroyed.</para>
<para>If the <parameter>handler</parameter> parameter to <function>sd_event_add_signal()</function> is
<constant>NULL</constant>, and the event source fires, this will be considered a request to exit the
event loop. In this case, the <parameter>userdata</parameter> parameter, cast to an integer, is passed as
the exit code parameter to
<citerefentry><refentrytitle>sd_event_exit</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
<para><function>sd_event_source_get_signal()</function> returns
the configured signal number of an event source created previously
with <function>sd_event_add_signal()</function>. It takes the

View File

@ -161,12 +161,10 @@
"floating", and will be destroyed implicitly when the event loop
itself is destroyed.</para>
<para>If the <parameter>handler</parameter> to
<function>sd_event_add_time()</function> is
<constant>NULL</constant>, and the event source fires, this will
be considered a request to exit the event loop. In this case, the
<parameter>userdata</parameter> parameter, cast to an integer, is
used for the exit code passed to
<para>If the <parameter>handler</parameter> parameter to <function>sd_event_add_time()</function> is
<constant>NULL</constant>, and the event source fires, this will be considered a request to exit the
event loop. In this case, the <parameter>userdata</parameter> parameter, cast to an integer, is passed as
the exit code parameter to
<citerefentry><refentrytitle>sd_event_exit</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
<para>Use <constant>CLOCK_BOOTTIME_ALARM</constant> and

View File

@ -74,6 +74,16 @@
conflict with regular exit codes returned by
<function>sd_event_loop()</function>, if these exit codes shall be
distinguishable.</para>
<para>Note that for most event source types passing the callback pointer as <constant>NULL</constant> in
the respective constructor call (i.e. in
<citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
…) has the effect of <function>sd_event_exit()</function> being invoked once the event source triggers,
with the specified userdata pointer cast to an integer as the exit code parameter. This is useful to
automatically terminate an event loop after some condition, such as a time-out or reception of
<constant>SIGTERM</constant> or similar. See the documentation for the respective constructor call for
details.</para>
</refsect1>
<refsect1>
@ -128,7 +138,12 @@
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd-event</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_new</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_exit</refentrytitle><manvolnum>3</manvolnum></citerefentry>
<citerefentry><refentrytitle>sd_event_add_exit</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_defer</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_inotify</refentrytitle><manvolnum>3</manvolnum></citerefentry>
</para>
</refsect1>

View File

@ -0,0 +1,108 @@
<?xml version='1.0'?>
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!-- SPDX-License-Identifier: LGPL-2.1+ -->
<refentry id="sd_event_source_set_exit_on_failure" xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sd_event_source_set_exit_on_failure</title>
<productname>systemd</productname>
</refentryinfo>
<refmeta>
<refentrytitle>sd_event_source_set_exit_on_failure</refentrytitle>
<manvolnum>3</manvolnum>
</refmeta>
<refnamediv>
<refname>sd_event_source_set_exit_on_failure</refname>
<refname>sd_event_source_get_exit_on_failure</refname>
<refpurpose>Set or retrieve the exit-on-failure feature of event sources</refpurpose>
</refnamediv>
<refsynopsisdiv>
<funcsynopsis>
<funcsynopsisinfo>#include &lt;systemd/sd-event.h&gt;</funcsynopsisinfo>
<funcprototype>
<funcdef>int <function>sd_event_source_set_exit_on_failure</function></funcdef>
<paramdef>sd_event_source *<parameter>source</parameter></paramdef>
<paramdef>int <parameter>b</parameter></paramdef>
</funcprototype>
<funcprototype>
<funcdef>int <function>sd_event_source_get_exit_on_failure</function></funcdef>
<paramdef>sd_event_source *<parameter>source</parameter></paramdef>
</funcprototype>
</funcsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para><function>sd_event_source_set_exit_on_failure()</function> may be used to set/unset the
exit-on-failure flag of the event source object specified as <parameter>source</parameter>. The flag
defaults to off. If on and the callback function set for the event source returns a failure code (i.e. a
negative value) the event loop is exited too, using the callback return code as the exit code for
<citerefentry><refentrytitle>sd_event_exit</refentrytitle><manvolnum>3</manvolnum></citerefentry>. If
off, the event source is disabled but the event loop continues to run. Setting this flag is useful for
"dominant" event sources that define the purpose and reason for the event loop, and whose failure hence
should propagate to the event loop itself — as opposed to "auxiliary" event sources whose failures should
remain local and affect the event source, but not propagate further.</para>
<para><function>sd_event_source_get_exit_on_failure()</function> may be used to query the flag currently
set for the event source object <parameter>source</parameter>.</para>
</refsect1>
<refsect1>
<title>Return Value</title>
<para>On success, <function>sd_event_source_set_exit_on_failure()</function> returns a non-negative
integer. <function>sd_event_source_get_exit_on_failure()</function> returns 0 if the flag is off, &gt; 0
if the flag is on. On failure, both return a negative errno-style error code.</para>
<refsect2>
<title>Errors</title>
<para>Returned errors may indicate the following problems:</para>
<variablelist>
<varlistentry>
<term><constant>-EINVAL</constant></term>
<listitem><para><parameter>source</parameter> is not a valid pointer to an
<structname>sd_event_source</structname> object.</para></listitem>
</varlistentry>
<varlistentry>
<term><constant>-EDOM</constant></term>
<listitem><para>The event source refers to an exit event source (as created with
<citerefentry><refentrytitle>sd_event_add_exit</refentrytitle><manvolnum>3</manvolnum></citerefentry>),
for which this functionality is not supported.</para></listitem>
</varlistentry>
</variablelist>
</refsect2>
</refsect1>
<xi:include href="libsystemd-pkgconfig.xml" />
<refsect1>
<title>See Also</title>
<para>
<citerefentry><refentrytitle>sd-event</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_child</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_inotify</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_defer</refentrytitle><manvolnum>3</manvolnum></citerefentry>
</para>
</refsect1>
</refentry>

View File

@ -726,6 +726,8 @@ LIBSYSTEMD_247 {
global:
sd_event_add_time_relative;
sd_event_source_set_time_relative;
sd_event_source_get_exit_on_failure;
sd_event_source_set_exit_on_failure;
sd_bus_error_has_names_sentinel;

View File

@ -60,6 +60,7 @@ struct sd_event_source {
bool pending:1;
bool dispatching:1;
bool floating:1;
bool exit_on_failure:1;
int64_t priority;
unsigned pending_index;

View File

@ -972,6 +972,12 @@ static sd_event_source *source_new(sd_event *e, bool floating, EventSourceType t
return s;
}
static int io_exit_callback(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
assert(s);
return sd_event_exit(sd_event_source_get_event(s), PTR_TO_INT(userdata));
}
_public_ int sd_event_add_io(
sd_event *e,
sd_event_source **ret,
@ -987,10 +993,12 @@ _public_ int sd_event_add_io(
assert_return(e = event_resolve(e), -ENOPKG);
assert_return(fd >= 0, -EBADF);
assert_return(!(events & ~(EPOLLIN|EPOLLOUT|EPOLLRDHUP|EPOLLPRI|EPOLLERR|EPOLLHUP|EPOLLET)), -EINVAL);
assert_return(callback, -EINVAL);
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
assert_return(!event_pid_changed(e), -ECHILD);
if (!callback)
callback = io_exit_callback;
s = source_new(e, !ret, SOURCE_IO);
if (!s)
return -ENOMEM;
@ -1235,6 +1243,12 @@ _public_ int sd_event_add_signal(
return 0;
}
static int child_exit_callback(sd_event_source *s, const siginfo_t *si, void *userdata) {
assert(s);
return sd_event_exit(sd_event_source_get_event(s), PTR_TO_INT(userdata));
}
static bool shall_use_pidfd(void) {
/* Mostly relevant for debugging, i.e. this is used in test-event.c to test the event loop once with and once without pidfd */
return getenv_bool_secure("SYSTEMD_PIDFD") != 0;
@ -1256,10 +1270,12 @@ _public_ int sd_event_add_child(
assert_return(pid > 1, -EINVAL);
assert_return(!(options & ~(WEXITED|WSTOPPED|WCONTINUED)), -EINVAL);
assert_return(options != 0, -EINVAL);
assert_return(callback, -EINVAL);
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
assert_return(!event_pid_changed(e), -ECHILD);
if (!callback)
callback = child_exit_callback;
if (e->n_enabled_child_sources == 0) {
/* Caller must block SIGCHLD before using us to watch children, even if pidfd is available,
* for compatibility with pre-pidfd and because we don't want the reap the child processes
@ -1357,10 +1373,12 @@ _public_ int sd_event_add_child_pidfd(
assert_return(pidfd >= 0, -EBADF);
assert_return(!(options & ~(WEXITED|WSTOPPED|WCONTINUED)), -EINVAL);
assert_return(options != 0, -EINVAL);
assert_return(callback, -EINVAL);
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
assert_return(!event_pid_changed(e), -ECHILD);
if (!callback)
callback = child_exit_callback;
if (e->n_enabled_child_sources == 0) {
r = signal_is_blocked(SIGCHLD);
if (r < 0)
@ -1426,6 +1444,12 @@ _public_ int sd_event_add_child_pidfd(
return 0;
}
static int generic_exit_callback(sd_event_source *s, void *userdata) {
assert(s);
return sd_event_exit(sd_event_source_get_event(s), PTR_TO_INT(userdata));
}
_public_ int sd_event_add_defer(
sd_event *e,
sd_event_source **ret,
@ -1437,10 +1461,12 @@ _public_ int sd_event_add_defer(
assert_return(e, -EINVAL);
assert_return(e = event_resolve(e), -ENOPKG);
assert_return(callback, -EINVAL);
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
assert_return(!event_pid_changed(e), -ECHILD);
if (!callback)
callback = generic_exit_callback;
s = source_new(e, !ret, SOURCE_DEFER);
if (!s)
return -ENOMEM;
@ -1471,10 +1497,12 @@ _public_ int sd_event_add_post(
assert_return(e, -EINVAL);
assert_return(e = event_resolve(e), -ENOPKG);
assert_return(callback, -EINVAL);
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
assert_return(!event_pid_changed(e), -ECHILD);
if (!callback)
callback = generic_exit_callback;
s = source_new(e, !ret, SOURCE_POST);
if (!s)
return -ENOMEM;
@ -1826,6 +1854,12 @@ static int inode_data_realize_watch(sd_event *e, struct inode_data *d) {
return 1;
}
static int inotify_exit_callback(sd_event_source *s, const struct inotify_event *event, void *userdata) {
assert(s);
return sd_event_exit(sd_event_source_get_event(s), PTR_TO_INT(userdata));
}
_public_ int sd_event_add_inotify(
sd_event *e,
sd_event_source **ret,
@ -1844,10 +1878,12 @@ _public_ int sd_event_add_inotify(
assert_return(e, -EINVAL);
assert_return(e = event_resolve(e), -ENOPKG);
assert_return(path, -EINVAL);
assert_return(callback, -EINVAL);
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
assert_return(!event_pid_changed(e), -ECHILD);
if (!callback)
callback = inotify_exit_callback;
/* Refuse IN_MASK_ADD since we coalesce watches on the same inode, and hence really don't want to merge
* masks. Or in other words, this whole code exists only to manage IN_MASK_ADD type operations for you, hence
* the user can't use them for us. */
@ -3183,16 +3219,21 @@ static int process_inotify(sd_event *e) {
}
static int source_dispatch(sd_event_source *s) {
_cleanup_(sd_event_unrefp) sd_event *saved_event = NULL;
EventSourceType saved_type;
int r = 0;
assert(s);
assert(s->pending || s->type == SOURCE_EXIT);
/* Save the event source type, here, so that we still know it after the event callback which might invalidate
* the event. */
/* Save the event source type, here, so that we still know it after the event callback which might
* invalidate the event. */
saved_type = s->type;
/* Similar, store a reference to the event loop object, so that we can still access it after the
* callback might have invalidated/disconnected the event source. */
saved_event = sd_event_ref(s->event);
if (!IN_SET(s->type, SOURCE_DEFER, SOURCE_EXIT)) {
r = source_set_pending(s, false);
if (r < 0)
@ -3299,9 +3340,15 @@ static int source_dispatch(sd_event_source *s) {
s->dispatching = false;
if (r < 0)
log_debug_errno(r, "Event source %s (type %s) returned error, disabling: %m",
strna(s->description), event_source_type_to_string(saved_type));
if (r < 0) {
log_debug_errno(r, "Event source %s (type %s) returned error, %s: %m",
strna(s->description),
event_source_type_to_string(saved_type),
s->exit_on_failure ? "exiting" : "disabling");
if (s->exit_on_failure)
(void) sd_event_exit(saved_event, r);
}
if (s->n_ref == 0)
source_free(s);
@ -3334,9 +3381,15 @@ static int event_prepare(sd_event *e) {
r = s->prepare(s, s->userdata);
s->dispatching = false;
if (r < 0)
log_debug_errno(r, "Prepare callback of event source %s (type %s) returned error, disabling: %m",
strna(s->description), event_source_type_to_string(s->type));
if (r < 0) {
log_debug_errno(r, "Prepare callback of event source %s (type %s) returned error, %s: %m",
strna(s->description),
event_source_type_to_string(s->type),
s->exit_on_failure ? "exiting" : "disabling");
if (s->exit_on_failure)
(void) sd_event_exit(e, r);
}
if (s->n_ref == 0)
source_free(s);
@ -3974,3 +4027,21 @@ _public_ int sd_event_source_set_floating(sd_event_source *s, int b) {
return 1;
}
_public_ int sd_event_source_get_exit_on_failure(sd_event_source *s) {
assert_return(s, -EINVAL);
assert_return(s->type != SOURCE_EXIT, -EDOM);
return s->exit_on_failure;
}
_public_ int sd_event_source_set_exit_on_failure(sd_event_source *s, int b) {
assert_return(s, -EINVAL);
assert_return(s->type != SOURCE_EXIT, -EDOM);
if (s->exit_on_failure == !!b)
return 0;
s->exit_on_failure = b;
return 1;
}

View File

@ -175,10 +175,6 @@ found:
return sd_event_exit(sd_device_monitor_get_event(monitor), 0);
}
static int device_timeout_handler(sd_event_source *s, uint64_t usec, void *userdata) {
return sd_event_exit(sd_event_source_get_event(s), -ETIMEDOUT);
}
static int device_wait_for_initialization_internal(
sd_device *_device,
const char *devlink,
@ -248,7 +244,7 @@ static int device_wait_for_initialization_internal(
r = sd_event_add_time_relative(
event, &timeout_source,
CLOCK_MONOTONIC, timeout, 0,
device_timeout_handler, NULL);
NULL, INT_TO_PTR(-ETIMEDOUT));
if (r < 0)
return log_error_errno(r, "Failed to add timeout event source: %m");
}

View File

@ -522,17 +522,14 @@ static int accept_cb(sd_event_source *s, int fd, uint32_t revents, void *userdat
r = add_connection_socket(context, nfd);
if (r < 0) {
log_error_errno(r, "Failed to accept connection, ignoring: %m");
safe_close(fd);
log_warning_errno(r, "Failed to accept connection, ignoring: %m");
safe_close(nfd);
}
}
r = sd_event_source_set_enabled(s, SD_EVENT_ONESHOT);
if (r < 0) {
log_error_errno(r, "Error while re-enabling listener with ONESHOT: %m");
sd_event_exit(context->event, r);
return r;
}
if (r < 0)
return log_error_errno(r, "Error while re-enabling listener with ONESHOT: %m");
return 1;
}
@ -561,11 +558,14 @@ static int add_listen_socket(Context *context, int fd) {
r = set_ensure_put(&context->listen, NULL, source);
if (r < 0) {
log_error_errno(r, "Failed to add source to set: %m");
sd_event_source_unref(source);
return r;
return log_error_errno(r, "Failed to add source to set: %m");
}
r = sd_event_source_set_exit_on_failure(source, true);
if (r < 0)
return log_error_errno(r, "Failed to enable exit-on-failure logic: %m");
/* Set the watcher to oneshot in case other processes are also
* watching to accept(). */
r = sd_event_source_set_enabled(source, SD_EVENT_ONESHOT);

View File

@ -160,6 +160,8 @@ int sd_event_source_set_destroy_callback(sd_event_source *s, sd_event_destroy_t
int sd_event_source_get_destroy_callback(sd_event_source *s, sd_event_destroy_t *ret);
int sd_event_source_get_floating(sd_event_source *s);
int sd_event_source_set_floating(sd_event_source *s, int b);
int sd_event_source_get_exit_on_failure(sd_event_source *s);
int sd_event_source_set_exit_on_failure(sd_event_source *s, int b);
/* Define helpers so that __attribute__((cleanup(sd_event_unrefp))) and similar may be used. */
_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_event, sd_event_unref);

View File

@ -414,6 +414,8 @@ static void test_foreach_pointer(void) {
int a, b, c, *i;
size_t k = 0;
log_info("/* %s */", __func__);
FOREACH_POINTER(i, &a, &b, &c) {
switch (k) {
@ -489,6 +491,17 @@ static void test_foreach_pointer(void) {
assert(k == 11);
}
static void test_ptr_to_int(void) {
log_info("/* %s */", __func__);
/* Primary reason to have this test is to validate that pointers are large enough to hold entire int range */
assert_se(PTR_TO_INT(INT_TO_PTR(0)) == 0);
assert_se(PTR_TO_INT(INT_TO_PTR(1)) == 1);
assert_se(PTR_TO_INT(INT_TO_PTR(-1)) == -1);
assert_se(PTR_TO_INT(INT_TO_PTR(INT_MAX)) == INT_MAX);
assert_se(PTR_TO_INT(INT_TO_PTR(INT_MIN)) == INT_MIN);
}
int main(int argc, char *argv[]) {
test_setup_logging(LOG_INFO);
@ -508,6 +521,7 @@ int main(int argc, char *argv[]) {
test_system_tasks_max();
test_system_tasks_max_scale();
test_foreach_pointer();
test_ptr_to_int();
return 0;
}

View File

@ -355,10 +355,6 @@ int udev_ctrl_send(struct udev_ctrl *uctrl, enum udev_ctrl_msg_type type, int in
return 0;
}
static int udev_ctrl_wait_io_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
return sd_event_exit(sd_event_source_get_event(s), 0);
}
int udev_ctrl_wait(struct udev_ctrl *uctrl, usec_t timeout) {
_cleanup_(sd_event_source_unrefp) sd_event_source *source_io = NULL, *source_timeout = NULL;
int r;
@ -385,7 +381,7 @@ int udev_ctrl_wait(struct udev_ctrl *uctrl, usec_t timeout) {
return r;
}
r = sd_event_add_io(uctrl->event, &source_io, uctrl->sock, EPOLLIN, udev_ctrl_wait_io_handler, NULL);
r = sd_event_add_io(uctrl->event, &source_io, uctrl->sock, EPOLLIN, NULL, INT_TO_PTR(0));
if (r < 0)
return r;