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:
commit
1378ac6989
|
@ -564,6 +564,10 @@ manpages = [
|
||||||
'SD_EVENT_ONESHOT',
|
'SD_EVENT_ONESHOT',
|
||||||
'sd_event_source_get_enabled'],
|
'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_floating', '3', ['sd_event_source_get_floating'], ''],
|
||||||
['sd_event_source_set_prepare', '3', [], ''],
|
['sd_event_source_set_prepare', '3', [], ''],
|
||||||
['sd_event_source_set_priority',
|
['sd_event_source_set_priority',
|
||||||
|
|
|
@ -150,11 +150,10 @@
|
||||||
<citerefentry
|
<citerefentry
|
||||||
project='man-pages'><refentrytitle>pthread_sigmask</refentrytitle><manvolnum>3</manvolnum></citerefentry>).</para>
|
project='man-pages'><refentrytitle>pthread_sigmask</refentrytitle><manvolnum>3</manvolnum></citerefentry>).</para>
|
||||||
|
|
||||||
<para>If the second parameter of
|
<para>If the second parameter of <function>sd_event_add_child()</function> is passed as
|
||||||
<function>sd_event_add_child()</function> is passed as NULL no
|
<constant>NULL</constant> no reference to the event source object is returned. In this case the event
|
||||||
reference to the event source object is returned. In this case the
|
source is considered "floating", and will be destroyed implicitly when the event loop itself is
|
||||||
event source is considered "floating", and will be destroyed
|
destroyed.</para>
|
||||||
implicitly when the event loop itself is destroyed.</para>
|
|
||||||
|
|
||||||
<para>Note that the <parameter>handler</parameter> function is
|
<para>Note that the <parameter>handler</parameter> function is
|
||||||
invoked at a time where the child process is not reaped yet (and
|
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
|
event sources are installed will not be reaped by the event loop
|
||||||
implementation.</para>
|
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
|
<para>If both a child process state change event source and a
|
||||||
<constant>SIGCHLD</constant> signal event source is installed in
|
<constant>SIGCHLD</constant> signal event source is installed in
|
||||||
the same event loop, the configured event source priorities decide
|
the same event loop, the configured event source priorities decide
|
||||||
|
|
|
@ -116,11 +116,17 @@
|
||||||
<constant>SD_EVENT_OFF</constant> with
|
<constant>SD_EVENT_OFF</constant> with
|
||||||
<citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
|
<citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
|
||||||
|
|
||||||
<para>If the second parameter of these functions is passed as
|
<para>If the second parameter of these functions is passed as <constant>NULL</constant> no reference to
|
||||||
NULL no reference to the event source object is returned. In this
|
the event source object is returned. In this case the event source is considered "floating", and will be
|
||||||
case the event source is considered "floating", and will be
|
destroyed implicitly when the event loop itself is destroyed.</para>
|
||||||
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>
|
||||||
|
|
||||||
<refsect1>
|
<refsect1>
|
||||||
|
|
|
@ -95,9 +95,16 @@
|
||||||
it with
|
it with
|
||||||
<citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
|
<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
|
<para>If the second parameter of <function>sd_event_add_inotify()</function> is passed as
|
||||||
event source object is returned. In this case the event source is considered "floating", and will be destroyed
|
<constant>NULL</constant> no reference to the event source object is returned. In this case the event
|
||||||
implicitly when the event loop itself is destroyed.</para>
|
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
|
<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
|
event source created previously with <function>sd_event_add_inotify()</function>. It takes the event source object
|
||||||
|
|
|
@ -161,6 +161,12 @@
|
||||||
"floating", and will be destroyed implicitly when the event loop
|
"floating", and will be destroyed implicitly when the event loop
|
||||||
itself is destroyed.</para>
|
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
|
<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
|
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
|
<function>sd_event_source_set_io_fd_own()</function> call (see below) the event source may optionally
|
||||||
|
|
|
@ -79,9 +79,7 @@
|
||||||
threads before this function is called (using <citerefentry
|
threads before this function is called (using <citerefentry
|
||||||
project='man-pages'><refentrytitle>sigprocmask</refentrytitle><manvolnum>2</manvolnum></citerefentry> or
|
project='man-pages'><refentrytitle>sigprocmask</refentrytitle><manvolnum>2</manvolnum></citerefentry> or
|
||||||
<citerefentry
|
<citerefentry
|
||||||
project='man-pages'><refentrytitle>pthread_sigmask</refentrytitle><manvolnum>3</manvolnum></citerefentry>). If
|
project='man-pages'><refentrytitle>pthread_sigmask</refentrytitle><manvolnum>3</manvolnum></citerefentry>).</para>
|
||||||
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>
|
|
||||||
|
|
||||||
<para>By default, the event source is enabled permanently
|
<para>By default, the event source is enabled permanently
|
||||||
(<constant>SD_EVENT_ON</constant>), but this may be changed with
|
(<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
|
"floating", and will be destroyed implicitly when the event loop
|
||||||
itself is destroyed.</para>
|
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
|
<para><function>sd_event_source_get_signal()</function> returns
|
||||||
the configured signal number of an event source created previously
|
the configured signal number of an event source created previously
|
||||||
with <function>sd_event_add_signal()</function>. It takes the
|
with <function>sd_event_add_signal()</function>. It takes the
|
||||||
|
|
|
@ -161,12 +161,10 @@
|
||||||
"floating", and will be destroyed implicitly when the event loop
|
"floating", and will be destroyed implicitly when the event loop
|
||||||
itself is destroyed.</para>
|
itself is destroyed.</para>
|
||||||
|
|
||||||
<para>If the <parameter>handler</parameter> to
|
<para>If the <parameter>handler</parameter> parameter to <function>sd_event_add_time()</function> is
|
||||||
<function>sd_event_add_time()</function> is
|
<constant>NULL</constant>, and the event source fires, this will be considered a request to exit the
|
||||||
<constant>NULL</constant>, and the event source fires, this will
|
event loop. In this case, the <parameter>userdata</parameter> parameter, cast to an integer, is passed as
|
||||||
be considered a request to exit the event loop. In this case, the
|
the exit code parameter to
|
||||||
<parameter>userdata</parameter> parameter, cast to an integer, is
|
|
||||||
used for the exit code passed to
|
|
||||||
<citerefentry><refentrytitle>sd_event_exit</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
|
<citerefentry><refentrytitle>sd_event_exit</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
|
||||||
|
|
||||||
<para>Use <constant>CLOCK_BOOTTIME_ALARM</constant> and
|
<para>Use <constant>CLOCK_BOOTTIME_ALARM</constant> and
|
||||||
|
|
|
@ -74,6 +74,16 @@
|
||||||
conflict with regular exit codes returned by
|
conflict with regular exit codes returned by
|
||||||
<function>sd_event_loop()</function>, if these exit codes shall be
|
<function>sd_event_loop()</function>, if these exit codes shall be
|
||||||
distinguishable.</para>
|
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>
|
||||||
|
|
||||||
<refsect1>
|
<refsect1>
|
||||||
|
@ -128,7 +138,12 @@
|
||||||
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
|
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
|
||||||
<citerefentry><refentrytitle>sd-event</refentrytitle><manvolnum>3</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_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>
|
</para>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
|
|
|
@ -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 <systemd/sd-event.h></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, > 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>
|
|
@ -726,6 +726,8 @@ LIBSYSTEMD_247 {
|
||||||
global:
|
global:
|
||||||
sd_event_add_time_relative;
|
sd_event_add_time_relative;
|
||||||
sd_event_source_set_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;
|
sd_bus_error_has_names_sentinel;
|
||||||
|
|
||||||
|
|
|
@ -60,6 +60,7 @@ struct sd_event_source {
|
||||||
bool pending:1;
|
bool pending:1;
|
||||||
bool dispatching:1;
|
bool dispatching:1;
|
||||||
bool floating:1;
|
bool floating:1;
|
||||||
|
bool exit_on_failure:1;
|
||||||
|
|
||||||
int64_t priority;
|
int64_t priority;
|
||||||
unsigned pending_index;
|
unsigned pending_index;
|
||||||
|
|
|
@ -972,6 +972,12 @@ static sd_event_source *source_new(sd_event *e, bool floating, EventSourceType t
|
||||||
return s;
|
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(
|
_public_ int sd_event_add_io(
|
||||||
sd_event *e,
|
sd_event *e,
|
||||||
sd_event_source **ret,
|
sd_event_source **ret,
|
||||||
|
@ -987,10 +993,12 @@ _public_ int sd_event_add_io(
|
||||||
assert_return(e = event_resolve(e), -ENOPKG);
|
assert_return(e = event_resolve(e), -ENOPKG);
|
||||||
assert_return(fd >= 0, -EBADF);
|
assert_return(fd >= 0, -EBADF);
|
||||||
assert_return(!(events & ~(EPOLLIN|EPOLLOUT|EPOLLRDHUP|EPOLLPRI|EPOLLERR|EPOLLHUP|EPOLLET)), -EINVAL);
|
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(e->state != SD_EVENT_FINISHED, -ESTALE);
|
||||||
assert_return(!event_pid_changed(e), -ECHILD);
|
assert_return(!event_pid_changed(e), -ECHILD);
|
||||||
|
|
||||||
|
if (!callback)
|
||||||
|
callback = io_exit_callback;
|
||||||
|
|
||||||
s = source_new(e, !ret, SOURCE_IO);
|
s = source_new(e, !ret, SOURCE_IO);
|
||||||
if (!s)
|
if (!s)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
@ -1235,6 +1243,12 @@ _public_ int sd_event_add_signal(
|
||||||
return 0;
|
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) {
|
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 */
|
/* 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;
|
return getenv_bool_secure("SYSTEMD_PIDFD") != 0;
|
||||||
|
@ -1256,10 +1270,12 @@ _public_ int sd_event_add_child(
|
||||||
assert_return(pid > 1, -EINVAL);
|
assert_return(pid > 1, -EINVAL);
|
||||||
assert_return(!(options & ~(WEXITED|WSTOPPED|WCONTINUED)), -EINVAL);
|
assert_return(!(options & ~(WEXITED|WSTOPPED|WCONTINUED)), -EINVAL);
|
||||||
assert_return(options != 0, -EINVAL);
|
assert_return(options != 0, -EINVAL);
|
||||||
assert_return(callback, -EINVAL);
|
|
||||||
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
|
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
|
||||||
assert_return(!event_pid_changed(e), -ECHILD);
|
assert_return(!event_pid_changed(e), -ECHILD);
|
||||||
|
|
||||||
|
if (!callback)
|
||||||
|
callback = child_exit_callback;
|
||||||
|
|
||||||
if (e->n_enabled_child_sources == 0) {
|
if (e->n_enabled_child_sources == 0) {
|
||||||
/* Caller must block SIGCHLD before using us to watch children, even if pidfd is available,
|
/* 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
|
* 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(pidfd >= 0, -EBADF);
|
||||||
assert_return(!(options & ~(WEXITED|WSTOPPED|WCONTINUED)), -EINVAL);
|
assert_return(!(options & ~(WEXITED|WSTOPPED|WCONTINUED)), -EINVAL);
|
||||||
assert_return(options != 0, -EINVAL);
|
assert_return(options != 0, -EINVAL);
|
||||||
assert_return(callback, -EINVAL);
|
|
||||||
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
|
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
|
||||||
assert_return(!event_pid_changed(e), -ECHILD);
|
assert_return(!event_pid_changed(e), -ECHILD);
|
||||||
|
|
||||||
|
if (!callback)
|
||||||
|
callback = child_exit_callback;
|
||||||
|
|
||||||
if (e->n_enabled_child_sources == 0) {
|
if (e->n_enabled_child_sources == 0) {
|
||||||
r = signal_is_blocked(SIGCHLD);
|
r = signal_is_blocked(SIGCHLD);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
|
@ -1426,6 +1444,12 @@ _public_ int sd_event_add_child_pidfd(
|
||||||
return 0;
|
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(
|
_public_ int sd_event_add_defer(
|
||||||
sd_event *e,
|
sd_event *e,
|
||||||
sd_event_source **ret,
|
sd_event_source **ret,
|
||||||
|
@ -1437,10 +1461,12 @@ _public_ int sd_event_add_defer(
|
||||||
|
|
||||||
assert_return(e, -EINVAL);
|
assert_return(e, -EINVAL);
|
||||||
assert_return(e = event_resolve(e), -ENOPKG);
|
assert_return(e = event_resolve(e), -ENOPKG);
|
||||||
assert_return(callback, -EINVAL);
|
|
||||||
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
|
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
|
||||||
assert_return(!event_pid_changed(e), -ECHILD);
|
assert_return(!event_pid_changed(e), -ECHILD);
|
||||||
|
|
||||||
|
if (!callback)
|
||||||
|
callback = generic_exit_callback;
|
||||||
|
|
||||||
s = source_new(e, !ret, SOURCE_DEFER);
|
s = source_new(e, !ret, SOURCE_DEFER);
|
||||||
if (!s)
|
if (!s)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
@ -1471,10 +1497,12 @@ _public_ int sd_event_add_post(
|
||||||
|
|
||||||
assert_return(e, -EINVAL);
|
assert_return(e, -EINVAL);
|
||||||
assert_return(e = event_resolve(e), -ENOPKG);
|
assert_return(e = event_resolve(e), -ENOPKG);
|
||||||
assert_return(callback, -EINVAL);
|
|
||||||
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
|
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
|
||||||
assert_return(!event_pid_changed(e), -ECHILD);
|
assert_return(!event_pid_changed(e), -ECHILD);
|
||||||
|
|
||||||
|
if (!callback)
|
||||||
|
callback = generic_exit_callback;
|
||||||
|
|
||||||
s = source_new(e, !ret, SOURCE_POST);
|
s = source_new(e, !ret, SOURCE_POST);
|
||||||
if (!s)
|
if (!s)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
@ -1826,6 +1854,12 @@ static int inode_data_realize_watch(sd_event *e, struct inode_data *d) {
|
||||||
return 1;
|
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(
|
_public_ int sd_event_add_inotify(
|
||||||
sd_event *e,
|
sd_event *e,
|
||||||
sd_event_source **ret,
|
sd_event_source **ret,
|
||||||
|
@ -1844,10 +1878,12 @@ _public_ int sd_event_add_inotify(
|
||||||
assert_return(e, -EINVAL);
|
assert_return(e, -EINVAL);
|
||||||
assert_return(e = event_resolve(e), -ENOPKG);
|
assert_return(e = event_resolve(e), -ENOPKG);
|
||||||
assert_return(path, -EINVAL);
|
assert_return(path, -EINVAL);
|
||||||
assert_return(callback, -EINVAL);
|
|
||||||
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
|
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
|
||||||
assert_return(!event_pid_changed(e), -ECHILD);
|
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
|
/* 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
|
* 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. */
|
* 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) {
|
static int source_dispatch(sd_event_source *s) {
|
||||||
|
_cleanup_(sd_event_unrefp) sd_event *saved_event = NULL;
|
||||||
EventSourceType saved_type;
|
EventSourceType saved_type;
|
||||||
int r = 0;
|
int r = 0;
|
||||||
|
|
||||||
assert(s);
|
assert(s);
|
||||||
assert(s->pending || s->type == SOURCE_EXIT);
|
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
|
/* Save the event source type, here, so that we still know it after the event callback which might
|
||||||
* the event. */
|
* invalidate the event. */
|
||||||
saved_type = s->type;
|
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)) {
|
if (!IN_SET(s->type, SOURCE_DEFER, SOURCE_EXIT)) {
|
||||||
r = source_set_pending(s, false);
|
r = source_set_pending(s, false);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
|
@ -3299,9 +3340,15 @@ static int source_dispatch(sd_event_source *s) {
|
||||||
|
|
||||||
s->dispatching = false;
|
s->dispatching = false;
|
||||||
|
|
||||||
if (r < 0)
|
if (r < 0) {
|
||||||
log_debug_errno(r, "Event source %s (type %s) returned error, disabling: %m",
|
log_debug_errno(r, "Event source %s (type %s) returned error, %s: %m",
|
||||||
strna(s->description), event_source_type_to_string(saved_type));
|
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)
|
if (s->n_ref == 0)
|
||||||
source_free(s);
|
source_free(s);
|
||||||
|
@ -3334,9 +3381,15 @@ static int event_prepare(sd_event *e) {
|
||||||
r = s->prepare(s, s->userdata);
|
r = s->prepare(s, s->userdata);
|
||||||
s->dispatching = false;
|
s->dispatching = false;
|
||||||
|
|
||||||
if (r < 0)
|
if (r < 0) {
|
||||||
log_debug_errno(r, "Prepare callback of event source %s (type %s) returned error, disabling: %m",
|
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));
|
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)
|
if (s->n_ref == 0)
|
||||||
source_free(s);
|
source_free(s);
|
||||||
|
@ -3974,3 +4027,21 @@ _public_ int sd_event_source_set_floating(sd_event_source *s, int b) {
|
||||||
|
|
||||||
return 1;
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -175,10 +175,6 @@ found:
|
||||||
return sd_event_exit(sd_device_monitor_get_event(monitor), 0);
|
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(
|
static int device_wait_for_initialization_internal(
|
||||||
sd_device *_device,
|
sd_device *_device,
|
||||||
const char *devlink,
|
const char *devlink,
|
||||||
|
@ -248,7 +244,7 @@ static int device_wait_for_initialization_internal(
|
||||||
r = sd_event_add_time_relative(
|
r = sd_event_add_time_relative(
|
||||||
event, &timeout_source,
|
event, &timeout_source,
|
||||||
CLOCK_MONOTONIC, timeout, 0,
|
CLOCK_MONOTONIC, timeout, 0,
|
||||||
device_timeout_handler, NULL);
|
NULL, INT_TO_PTR(-ETIMEDOUT));
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to add timeout event source: %m");
|
return log_error_errno(r, "Failed to add timeout event source: %m");
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
r = add_connection_socket(context, nfd);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
log_error_errno(r, "Failed to accept connection, ignoring: %m");
|
log_warning_errno(r, "Failed to accept connection, ignoring: %m");
|
||||||
safe_close(fd);
|
safe_close(nfd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
r = sd_event_source_set_enabled(s, SD_EVENT_ONESHOT);
|
r = sd_event_source_set_enabled(s, SD_EVENT_ONESHOT);
|
||||||
if (r < 0) {
|
if (r < 0)
|
||||||
log_error_errno(r, "Error while re-enabling listener with ONESHOT: %m");
|
return log_error_errno(r, "Error while re-enabling listener with ONESHOT: %m");
|
||||||
sd_event_exit(context->event, r);
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -561,11 +558,14 @@ static int add_listen_socket(Context *context, int fd) {
|
||||||
|
|
||||||
r = set_ensure_put(&context->listen, NULL, source);
|
r = set_ensure_put(&context->listen, NULL, source);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
log_error_errno(r, "Failed to add source to set: %m");
|
|
||||||
sd_event_source_unref(source);
|
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
|
/* Set the watcher to oneshot in case other processes are also
|
||||||
* watching to accept(). */
|
* watching to accept(). */
|
||||||
r = sd_event_source_set_enabled(source, SD_EVENT_ONESHOT);
|
r = sd_event_source_set_enabled(source, SD_EVENT_ONESHOT);
|
||||||
|
|
|
@ -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_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_get_floating(sd_event_source *s);
|
||||||
int sd_event_source_set_floating(sd_event_source *s, int b);
|
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. */
|
/* Define helpers so that __attribute__((cleanup(sd_event_unrefp))) and similar may be used. */
|
||||||
_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_event, sd_event_unref);
|
_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_event, sd_event_unref);
|
||||||
|
|
|
@ -414,6 +414,8 @@ static void test_foreach_pointer(void) {
|
||||||
int a, b, c, *i;
|
int a, b, c, *i;
|
||||||
size_t k = 0;
|
size_t k = 0;
|
||||||
|
|
||||||
|
log_info("/* %s */", __func__);
|
||||||
|
|
||||||
FOREACH_POINTER(i, &a, &b, &c) {
|
FOREACH_POINTER(i, &a, &b, &c) {
|
||||||
switch (k) {
|
switch (k) {
|
||||||
|
|
||||||
|
@ -489,6 +491,17 @@ static void test_foreach_pointer(void) {
|
||||||
assert(k == 11);
|
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[]) {
|
int main(int argc, char *argv[]) {
|
||||||
test_setup_logging(LOG_INFO);
|
test_setup_logging(LOG_INFO);
|
||||||
|
|
||||||
|
@ -508,6 +521,7 @@ int main(int argc, char *argv[]) {
|
||||||
test_system_tasks_max();
|
test_system_tasks_max();
|
||||||
test_system_tasks_max_scale();
|
test_system_tasks_max_scale();
|
||||||
test_foreach_pointer();
|
test_foreach_pointer();
|
||||||
|
test_ptr_to_int();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -355,10 +355,6 @@ int udev_ctrl_send(struct udev_ctrl *uctrl, enum udev_ctrl_msg_type type, int in
|
||||||
return 0;
|
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) {
|
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;
|
_cleanup_(sd_event_source_unrefp) sd_event_source *source_io = NULL, *source_timeout = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
@ -385,7 +381,7 @@ int udev_ctrl_wait(struct udev_ctrl *uctrl, usec_t timeout) {
|
||||||
return r;
|
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)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue