1
0
mirror of https://github.com/systemd/systemd synced 2026-03-31 20:24:50 +02:00

Compare commits

..

No commits in common. "10c79431a0e2d4968921f126407f563355302b48" and "98ae19d9fe5cbdaefae600c5b906cacd1a48c57a" have entirely different histories.

13 changed files with 38 additions and 464 deletions

View File

@ -302,15 +302,6 @@
<xi:include href="version-info.xml" xpointer="v259"/></listitem> <xi:include href="version-info.xml" xpointer="v259"/></listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><option>--same-root-dir</option></term>
<listitem><para>Execute the <command>run0</command> session in the same root directory that the
<command>run0</command> command is executed in.</para>
<xi:include href="version-info.xml" xpointer="v259"/></listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><option>--machine=</option></term> <term><option>--machine=</option></term>

View File

@ -116,9 +116,8 @@
parameter specifies the PID of the process to watch, which must be a direct child process of the invoking parameter specifies the PID of the process to watch, which must be a direct child process of the invoking
process. The <parameter>options</parameter> parameter determines which state changes will be watched for. process. The <parameter>options</parameter> parameter determines which state changes will be watched for.
It must contain an OR-ed mask of <constant>WEXITED</constant> (watch for the child process terminating), It must contain an OR-ed mask of <constant>WEXITED</constant> (watch for the child process terminating),
<constant>WSTOPPED</constant> (watch for the child process being stopped by a signal), <constant>WSTOPPED</constant> (watch for the child process being stopped by a signal), and
<constant>WCONTINUED</constant> (watch for the child process being resumed by a signal) and <constant>WCONTINUED</constant> (watch for the child process being resumed by a signal). See
<constant>WNOWAIT</constant> (Do not reap the child process after it exits). See
<citerefentry project='man-pages'><refentrytitle>waitid</refentrytitle><manvolnum>2</manvolnum></citerefentry> <citerefentry project='man-pages'><refentrytitle>waitid</refentrytitle><manvolnum>2</manvolnum></citerefentry>
for further information.</para> for further information.</para>

View File

@ -1,116 +0,0 @@
<?xml version='1.0'?>
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
<!-- SPDX-License-Identifier: LGPL-2.1-or-later -->
<refentry id="sd_event_set_exit_on_idle" xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sd_event_set_exit_on_idle</title>
<productname>systemd</productname>
</refentryinfo>
<refmeta>
<refentrytitle>sd_event_set_exit_on_idle</refentrytitle>
<manvolnum>3</manvolnum>
</refmeta>
<refnamediv>
<refname>sd_event_set_exit_on_idle</refname>
<refname>sd_event_get_exit_on_idle</refname>
<refpurpose>Enable event loop exit-on-idle support</refpurpose>
</refnamediv>
<refsynopsisdiv>
<funcsynopsis>
<funcsynopsisinfo>#include &lt;systemd/sd-event.h&gt;</funcsynopsisinfo>
<funcprototype>
<funcdef>int <function>sd_event_set_exit_on_idle</function></funcdef>
<paramdef>sd_event *<parameter>event</parameter></paramdef>
<paramdef>int b</paramdef>
</funcprototype>
<funcprototype>
<funcdef>int <function>sd_event_get_exit_on_idle</function></funcdef>
<paramdef>sd_event *<parameter>event</parameter></paramdef>
</funcprototype>
</funcsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para><function>sd_event_set_exit_on_idle()</function> may be used to
enable or disable the exit-on-idle support in the
event loop object specified in the <parameter>event</parameter>
parameter. If enabled, the event loop will exit with a zero exit code
there are no more enabled (<constant>SD_EVENT_ON</constant>, <constant>SD_EVENT_ONESHOT</constant>),
non-exit, non-post event sources.</para>
<para><function>sd_event_get_exit_on_idle()</function> may be used to
determine whether exit-on-idle support was previously requested by a
call to <function>sd_event_set_exit_on_idle()</function> with a true
<parameter>b</parameter> parameter and successfully enabled.</para>
</refsect1>
<refsect1>
<title>Return Value</title>
<para>On success, <function>sd_event_set_exit_on_idle()</function> and
<function>sd_event_get_exit_on_idle()</function> return a non-zero positive integer if the exit-on-idle
support was successfully enabled. They return zero if the exit-on-idle support was explicitly disabled
with a false <parameter>b</parameter> parameter. On failure, they 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>-ECHILD</constant></term>
<listitem><para>The event loop has been created in a different process, library or module instance.</para></listitem>
</varlistentry>
<varlistentry>
<term><constant>-EINVAL</constant></term>
<listitem><para>The passed event loop object was invalid.</para></listitem>
</varlistentry>
</variablelist>
</refsect2>
</refsect1>
<xi:include href="libsystemd-pkgconfig.xml" />
<refsect1>
<title>History</title>
<para><function>sd_event_set_exit_on_idle()</function> and
<function>sd_event_get_exit_on_idle()</function> were added in version 259.</para>
</refsect1>
<refsect1>
<title>See Also</title>
<para><simplelist type="inline">
<member><citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry></member>
<member><citerefentry><refentrytitle>sd-event</refentrytitle><manvolnum>3</manvolnum></citerefentry></member>
<member><citerefentry><refentrytitle>sd_event_new</refentrytitle><manvolnum>3</manvolnum></citerefentry></member>
<member><citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry></member>
<member><citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry></member>
<member><citerefentry><refentrytitle>sd_event_add_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry></member>
<member><citerefentry><refentrytitle>sd_event_add_child</refentrytitle><manvolnum>3</manvolnum></citerefentry></member>
<member><citerefentry><refentrytitle>sd_event_add_inotify</refentrytitle><manvolnum>3</manvolnum></citerefentry></member>
<member><citerefentry><refentrytitle>sd_event_add_defer</refentrytitle><manvolnum>3</manvolnum></citerefentry></member>
<member><citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry></member>
</simplelist></para>
</refsect1>
</refentry>

View File

@ -94,7 +94,6 @@ typedef enum TimestampStyle TimestampStyle;
typedef enum UnitActiveState UnitActiveState; typedef enum UnitActiveState UnitActiveState;
typedef enum UnitDependency UnitDependency; typedef enum UnitDependency UnitDependency;
typedef enum UnitType UnitType; typedef enum UnitType UnitType;
typedef enum WaitFlags WaitFlags;
typedef struct Hashmap Hashmap; typedef struct Hashmap Hashmap;
typedef struct HashmapBase HashmapBase; typedef struct HashmapBase HashmapBase;

View File

@ -58,9 +58,7 @@ static LogContext* log_context_detach(LogContext *c) {
LogContext* log_context_new(const char *key, const char *value) { LogContext* log_context_new(const char *key, const char *value) {
assert(key); assert(key);
assert(endswith(key, "=")); assert(endswith(key, "="));
assert(value);
if (!value)
return NULL;
LIST_FOREACH(ll, i, _log_context) LIST_FOREACH(ll, i, _log_context)
if (i->key == key && i->value == value) if (i->key == key && i->value == value)

View File

@ -1081,7 +1081,5 @@ global:
LIBSYSTEMD_259 { LIBSYSTEMD_259 {
global: global:
sd_event_set_exit_on_idle;
sd_event_get_exit_on_idle;
sd_varlink_is_connected; sd_varlink_is_connected;
} LIBSYSTEMD_258; } LIBSYSTEMD_258;

View File

@ -48,7 +48,7 @@ static bool EVENT_SOURCE_WATCH_PIDFD(const sd_event_source *s) {
/* Returns true if this is a PID event source and can be implemented by watching EPOLLIN */ /* Returns true if this is a PID event source and can be implemented by watching EPOLLIN */
return s && return s &&
s->type == SOURCE_CHILD && s->type == SOURCE_CHILD &&
(s->child.options & ~WNOWAIT) == WEXITED; s->child.options == WEXITED;
} }
static bool event_source_is_online(sd_event_source *s) { static bool event_source_is_online(sd_event_source *s) {
@ -157,7 +157,6 @@ struct sd_event {
bool need_process_child:1; bool need_process_child:1;
bool watchdog:1; bool watchdog:1;
bool profile_delays:1; bool profile_delays:1;
bool exit_on_idle:1;
int exit_code; int exit_code;
@ -1584,7 +1583,7 @@ _public_ int sd_event_add_child(
assert_return(e, -EINVAL); assert_return(e, -EINVAL);
assert_return(e = event_resolve(e), -ENOPKG); assert_return(e = event_resolve(e), -ENOPKG);
assert_return(pid > 1, -EINVAL); assert_return(pid > 1, -EINVAL);
assert_return(!(options & ~(WEXITED|WSTOPPED|WCONTINUED|WNOWAIT)), -EINVAL); assert_return(!(options & ~(WEXITED|WSTOPPED|WCONTINUED)), -EINVAL);
assert_return(options != 0, -EINVAL); assert_return(options != 0, -EINVAL);
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
assert_return(!event_origin_changed(e), -ECHILD); assert_return(!event_origin_changed(e), -ECHILD);
@ -1676,7 +1675,7 @@ _public_ int sd_event_add_child_pidfd(
assert_return(e, -EINVAL); assert_return(e, -EINVAL);
assert_return(e = event_resolve(e), -ENOPKG); assert_return(e = event_resolve(e), -ENOPKG);
assert_return(pidfd >= 0, -EBADF); assert_return(pidfd >= 0, -EBADF);
assert_return(!(options & ~(WEXITED|WSTOPPED|WCONTINUED|WNOWAIT)), -EINVAL); assert_return(!(options & ~(WEXITED|WSTOPPED|WCONTINUED)), -EINVAL);
assert_return(options != 0, -EINVAL); assert_return(options != 0, -EINVAL);
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
assert_return(!event_origin_changed(e), -ECHILD); assert_return(!event_origin_changed(e), -ECHILD);
@ -2988,11 +2987,9 @@ static int event_source_online(
break; break;
case SOURCE_MEMORY_PRESSURE: case SOURCE_MEMORY_PRESSURE:
if (s->memory_pressure.write_buffer_size == 0) {
r = source_memory_pressure_register(s, enabled); r = source_memory_pressure_register(s, enabled);
if (r < 0) if (r < 0)
return r; return r;
}
break; break;
@ -3045,8 +3042,16 @@ _public_ int sd_event_source_set_enabled(sd_event_source *s, int m) {
if (m == SD_EVENT_OFF) if (m == SD_EVENT_OFF)
r = event_source_offline(s, m, s->ratelimited); r = event_source_offline(s, m, s->ratelimited);
else else {
if (s->enabled != SD_EVENT_OFF) {
/* Switching from "on" to "oneshot" or back? If that's the case, we can take a shortcut, the
* event source is already enabled after all. */
s->enabled = m;
return 0;
}
r = event_source_online(s, m, s->ratelimited); r = event_source_online(s, m, s->ratelimited);
}
if (r < 0) if (r < 0)
return r; return r;
@ -3690,7 +3695,7 @@ static int process_child(sd_event *e, int64_t threshold, int64_t *ret_min_priori
zero(s->child.siginfo); zero(s->child.siginfo);
if (waitid(P_PIDFD, s->child.pidfd, &s->child.siginfo, if (waitid(P_PIDFD, s->child.pidfd, &s->child.siginfo,
WNOHANG | (s->child.options & WEXITED ? WNOWAIT : 0) | (s->child.options & ~WNOWAIT)) < 0) WNOHANG | (s->child.options & WEXITED ? WNOWAIT : 0) | s->child.options) < 0)
return negative_errno(); return negative_errno();
if (s->child.siginfo.si_pid != 0) { if (s->child.siginfo.si_pid != 0) {
@ -3738,6 +3743,7 @@ static int process_pidfd(sd_event *e, sd_event_source *s, uint32_t revents) {
/* Note that pidfd would also generate EPOLLHUP when the process gets reaped. But at this point we /* Note that pidfd would also generate EPOLLHUP when the process gets reaped. But at this point we
* only permit EPOLLIN, under the assumption that upon EPOLLHUP the child source should already * only permit EPOLLIN, under the assumption that upon EPOLLHUP the child source should already
* be set to pending, and we would have returned early above. */ * be set to pending, and we would have returned early above. */
assert(!s->child.exited);
zero(s->child.siginfo); zero(s->child.siginfo);
if (waitid(P_PIDFD, s->child.pidfd, &s->child.siginfo, WNOHANG | WNOWAIT | s->child.options) < 0) if (waitid(P_PIDFD, s->child.pidfd, &s->child.siginfo, WNOHANG | WNOWAIT | s->child.options) < 0)
@ -4077,22 +4083,6 @@ static int source_memory_pressure_initiate_dispatch(sd_event_source *s) {
return 0; /* go on, dispatch to user callback */ return 0; /* go on, dispatch to user callback */
} }
static int mark_post_sources_pending(sd_event *e) {
sd_event_source *z;
int r;
SET_FOREACH(z, e->post_sources) {
if (event_source_is_offline(z))
continue;
r = source_set_pending(z, true);
if (r < 0)
return r;
}
return 0;
}
static int source_dispatch(sd_event_source *s) { static int source_dispatch(sd_event_source *s) {
EventSourceType saved_type; EventSourceType saved_type;
sd_event *saved_event; sd_event *saved_event;
@ -4120,24 +4110,26 @@ static int source_dispatch(sd_event_source *s) {
return 1; return 1;
} }
if (IN_SET(s->type, SOURCE_DEFER, SOURCE_EXIT)) { if (!IN_SET(s->type, SOURCE_DEFER, SOURCE_EXIT)) {
/* Make sure this event source is moved to the end of the priority list now. We do this here
* because defer and exit event sources are always pending from the moment they're added so
* the same logic in source_set_pending() is never triggered. */
s->pending_iteration = s->event->iteration;
event_source_pp_prioq_reshuffle(s);
} else {
r = source_set_pending(s, false); r = source_set_pending(s, false);
if (r < 0) if (r < 0)
return r; return r;
} }
if (s->type != SOURCE_POST) { if (s->type != SOURCE_POST) {
sd_event_source *z;
/* If we execute a non-post source, let's mark all post sources as pending. */ /* If we execute a non-post source, let's mark all post sources as pending. */
r = mark_post_sources_pending(s->event);
SET_FOREACH(z, s->event->post_sources) {
if (event_source_is_offline(z))
continue;
r = source_set_pending(z, true);
if (r < 0) if (r < 0)
return r; return r;
} }
}
if (s->type == SOURCE_MEMORY_PRESSURE) { if (s->type == SOURCE_MEMORY_PRESSURE) {
r = source_memory_pressure_initiate_dispatch(s); r = source_memory_pressure_initiate_dispatch(s);
@ -4180,10 +4172,9 @@ static int source_dispatch(sd_event_source *s) {
r = s->child.callback(s, &s->child.siginfo, s->userdata); r = s->child.callback(s, &s->child.siginfo, s->userdata);
/* Now, reap the PID for good (unless WNOWAIT was specified by the caller). */ /* Now, reap the PID for good. */
if (zombie) { if (zombie) {
(void) waitid(P_PIDFD, s->child.pidfd, &s->child.siginfo, WNOHANG|WEXITED|(s->child.options & WNOWAIT)); (void) waitid(P_PIDFD, s->child.pidfd, &s->child.siginfo, WNOHANG|WEXITED);
if (!FLAGS_SET(s->child.options, WNOWAIT))
s->child.waited = true; s->child.waited = true;
} }
@ -4246,14 +4237,6 @@ static int source_dispatch(sd_event_source *s) {
s->dispatching = false; s->dispatching = false;
if (saved_type != SOURCE_POST) {
/* More post sources might have been added while executing the callback, let's make sure
* those are marked pending as well. */
r = mark_post_sources_pending(saved_event);
if (r < 0)
return r;
}
finish: finish:
if (r < 0) { if (r < 0) {
log_debug_errno(r, "Event source %s (type %s) returned error, %s: %m", log_debug_errno(r, "Event source %s (type %s) returned error, %s: %m",
@ -4429,28 +4412,6 @@ static int event_memory_pressure_write_list(sd_event *e) {
return 0; return 0;
} }
static bool event_loop_idle(sd_event *e) {
assert(e);
LIST_FOREACH(sources, s, e->sources) {
/* Exit sources only trigger on exit, so whether they're enabled or not doesn't matter when
* we're deciding if the event loop is idle or not. */
if (s->type == SOURCE_EXIT)
continue;
if (s->enabled == SD_EVENT_OFF)
continue;
/* Post event sources always need another active event source to become pending. */
if (s->type == SOURCE_POST && !s->pending)
continue;
return false;
}
return true;
}
_public_ int sd_event_prepare(sd_event *e) { _public_ int sd_event_prepare(sd_event *e) {
int r; int r;
@ -4468,9 +4429,6 @@ _public_ int sd_event_prepare(sd_event *e) {
/* Make sure that none of the preparation callbacks ends up freeing the event source under our feet */ /* Make sure that none of the preparation callbacks ends up freeing the event source under our feet */
PROTECT_EVENT(e); PROTECT_EVENT(e);
if (!e->exit_requested && e->exit_on_idle && event_loop_idle(e))
(void) sd_event_exit(e, 0);
if (e->exit_requested) if (e->exit_requested)
goto pending; goto pending;
@ -5275,22 +5233,6 @@ _public_ int sd_event_set_signal_exit(sd_event *e, int b) {
return change; return change;
} }
_public_ int sd_event_set_exit_on_idle(sd_event *e, int b) {
assert_return(e, -EINVAL);
assert_return(e = event_resolve(e), -ENOPKG);
assert_return(!event_origin_changed(e), -ECHILD);
return e->exit_on_idle = b;
}
_public_ int sd_event_get_exit_on_idle(sd_event *e) {
assert_return(e, -EINVAL);
assert_return(e = event_resolve(e), -ENOPKG);
assert_return(!event_origin_changed(e), -ECHILD);
return e->exit_on_idle;
}
_public_ int sd_event_source_set_memory_pressure_type(sd_event_source *s, const char *ty) { _public_ int sd_event_source_set_memory_pressure_type(sd_event_source *s, const char *ty) {
_cleanup_free_ char *b = NULL; _cleanup_free_ char *b = NULL;
_cleanup_free_ void *w = NULL; _cleanup_free_ void *w = NULL;

View File

@ -946,225 +946,4 @@ TEST(leave_ratelimit) {
ASSERT_TRUE(manually_left_ratelimit); ASSERT_TRUE(manually_left_ratelimit);
} }
static int defer_post_handler(sd_event_source *s, void *userdata) {
bool *dispatched_post = ASSERT_PTR(userdata);
*dispatched_post = true;
return 0;
}
static int defer_adds_post_handler(sd_event_source *s, void *userdata) {
sd_event *e = sd_event_source_get_event(s);
/* Add a post event source from within the defer handler */
ASSERT_OK(sd_event_add_post(e, NULL, defer_post_handler, userdata));
return 0;
}
TEST(defer_add_post) {
_cleanup_(sd_event_unrefp) sd_event *e = NULL;
bool dispatched_post = false;
ASSERT_OK(sd_event_default(&e));
/* Add a oneshot defer event source that will add a post event source */
ASSERT_OK(sd_event_add_defer(e, NULL, defer_adds_post_handler, &dispatched_post));
/* Run one iteration - this should dispatch the defer handler */
ASSERT_OK_POSITIVE(sd_event_run(e, UINT64_MAX));
/* The post handler should have been added but not yet dispatched */
ASSERT_FALSE(dispatched_post);
/* Run another iteration - this should dispatch the post handler */
ASSERT_OK_POSITIVE(sd_event_run(e, 0));
/* Now the post handler should have been dispatched */
ASSERT_TRUE(dispatched_post);
}
static int child_handler_wnowait(sd_event_source *s, const siginfo_t *si, void *userdata) {
int *counter = ASSERT_PTR(userdata);
(*counter)++;
if (*counter == 5)
ASSERT_OK(sd_event_exit(sd_event_source_get_event(s), 0));
return 0;
}
TEST(child_wnowait) {
_cleanup_(sd_event_unrefp) sd_event *e = NULL;
ASSERT_OK(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD));
ASSERT_OK(sd_event_default(&e));
/* Fork a subprocess */
pid_t pid;
ASSERT_OK_ERRNO(pid = fork());
if (pid == 0)
/* Child process - exit with a specific code */
_exit(42);
/* Add a child source with WNOWAIT flag */
_cleanup_(sd_event_source_unrefp) sd_event_source *s = NULL;
int counter = 0;
ASSERT_OK(sd_event_add_child(e, &s, pid, WEXITED|WNOWAIT, child_handler_wnowait, &counter));
ASSERT_OK(sd_event_source_set_enabled(s, SD_EVENT_ON));
/* Run the event loop - this should call the handler */
ASSERT_OK(sd_event_loop(e));
ASSERT_EQ(counter, 5);
/* Since we used WNOWAIT, the child should still be waitable */
siginfo_t si = {};
ASSERT_OK_ERRNO(waitid(P_PID, pid, &si, WEXITED|WNOHANG));
ASSERT_EQ(si.si_pid, pid);
ASSERT_EQ(si.si_code, CLD_EXITED);
ASSERT_EQ(si.si_status, 42);
}
TEST(child_pidfd_wnowait) {
_cleanup_(sd_event_unrefp) sd_event *e = NULL;
ASSERT_OK(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD));
ASSERT_OK(sd_event_default(&e));
/* Fork a subprocess */
pid_t pid;
ASSERT_OK_ERRNO(pid = fork());
if (pid == 0)
/* Child process - exit with a specific code */
_exit(42);
_cleanup_close_ int pidfd = -EBADF;
ASSERT_OK_ERRNO(pidfd = pidfd_open(pid, 0));
/* Add a child source with WNOWAIT flag */
_cleanup_(sd_event_source_unrefp) sd_event_source *s = NULL;
int counter = 0;
ASSERT_OK(sd_event_add_child_pidfd(e, &s, pidfd, WEXITED|WNOWAIT, child_handler_wnowait, &counter));
ASSERT_OK(sd_event_source_set_enabled(s, SD_EVENT_ON));
/* Run the event loop - this should call the handler */
ASSERT_OK(sd_event_loop(e));
ASSERT_EQ(counter, 5);
/* Since we used WNOWAIT, the child should still be waitable */
siginfo_t si = {};
ASSERT_OK_ERRNO(waitid(P_PIDFD, pidfd, &si, WEXITED|WNOHANG));
ASSERT_EQ(si.si_pid, pid);
ASSERT_EQ(si.si_code, CLD_EXITED);
ASSERT_EQ(si.si_status, 42);
}
static int exit_on_idle_defer_handler(sd_event_source *s, void *userdata) {
unsigned *c = ASSERT_PTR(userdata);
/* Should not be reached on third call because the event loop should exit before */
ASSERT_LT(*c, 2u);
(*c)++;
/* Disable ourselves, which should trigger exit-on-idle after the second iteration */
if (*c == 2)
sd_event_source_set_enabled(s, SD_EVENT_OFF);
return 0;
}
static int exit_on_idle_post_handler(sd_event_source *s, void *userdata) {
unsigned *c = ASSERT_PTR(userdata);
/* Should not be reached on third call because the event loop should exit before */
ASSERT_LT(*c, 2u);
(*c)++;
return 0;
}
static int exit_on_idle_exit_handler(sd_event_source *s, void *userdata) {
return 0;
}
TEST(exit_on_idle) {
_cleanup_(sd_event_unrefp) sd_event *e = NULL;
ASSERT_OK(sd_event_new(&e));
ASSERT_OK(sd_event_set_exit_on_idle(e, true));
ASSERT_OK_POSITIVE(sd_event_get_exit_on_idle(e));
/* Create a recurring defer event source. */
_cleanup_(sd_event_source_unrefp) sd_event_source *d = NULL;
unsigned dc = 0;
ASSERT_OK(sd_event_add_defer(e, &d, exit_on_idle_defer_handler, &dc));
ASSERT_OK(sd_event_source_set_enabled(d, SD_EVENT_ON));
/* This post event source should not keep the event loop running after the defer source is disabled. */
_cleanup_(sd_event_source_unrefp) sd_event_source *p = NULL;
unsigned pc = 0;
ASSERT_OK(sd_event_add_post(e, &p, exit_on_idle_post_handler, &pc));
ASSERT_OK(sd_event_source_set_enabled(p, SD_EVENT_ON));
ASSERT_OK(sd_event_source_set_priority(p, SD_EVENT_PRIORITY_IMPORTANT));
/* And neither should this exit event source. */
ASSERT_OK(sd_event_add_exit(e, NULL, exit_on_idle_exit_handler, NULL));
/* Run the event loop - it should exit after we disable the event source */
ASSERT_OK(sd_event_loop(e));
ASSERT_EQ(dc, 2u);
ASSERT_EQ(pc, 2u);
}
TEST(exit_on_idle_no_sources) {
_cleanup_(sd_event_unrefp) sd_event *e = NULL;
ASSERT_OK(sd_event_new(&e));
ASSERT_OK(sd_event_set_exit_on_idle(e, true));
/* Running loop with no sources should return immediately with success */
ASSERT_OK(sd_event_loop(e));
}
static int defer_fair_handler(sd_event_source *s, void *userdata) {
unsigned *counter = ASSERT_PTR(userdata);
/* If we're about to increment above 5, exit the event loop */
if (*counter >= 5)
return sd_event_exit(sd_event_source_get_event(s), 0);
(*counter)++;
return 0;
}
TEST(defer_fair_scheduling) {
_cleanup_(sd_event_unrefp) sd_event *e = NULL;
sd_event_source *sources[5] = {};
unsigned counters[5] = {};
ASSERT_OK(sd_event_new(&e));
ASSERT_OK(sd_event_set_exit_on_idle(e, true));
/* Create 5 defer sources with equal priority */
for (unsigned i = 0; i < 5; i++) {
ASSERT_OK(sd_event_add_defer(e, &sources[i], defer_fair_handler, &counters[i]));
ASSERT_OK(sd_event_source_set_enabled(sources[i], SD_EVENT_ON));
}
/* Run the event loop until one of the handlers exits */
ASSERT_OK(sd_event_loop(e));
/* All counters should be equal to 5, demonstrating fair scheduling */
for (unsigned i = 0; i < 5; i++) {
ASSERT_EQ(counters[i], 5u);
sd_event_source_unref(sources[i]);
}
}
DEFINE_TEST_MAIN(LOG_DEBUG); DEFINE_TEST_MAIN(LOG_DEBUG);

View File

@ -899,7 +899,6 @@ static int parse_argv_sudo_mode(int argc, char *argv[]) {
ARG_AREA, ARG_AREA,
ARG_VIA_SHELL, ARG_VIA_SHELL,
ARG_EMPOWER, ARG_EMPOWER,
ARG_SAME_ROOT_DIR,
}; };
/* If invoked as "run0" binary, let's expose a more sudo-like interface. We add various extensions /* If invoked as "run0" binary, let's expose a more sudo-like interface. We add various extensions
@ -930,7 +929,6 @@ static int parse_argv_sudo_mode(int argc, char *argv[]) {
{ "lightweight", required_argument, NULL, ARG_LIGHTWEIGHT }, { "lightweight", required_argument, NULL, ARG_LIGHTWEIGHT },
{ "area", required_argument, NULL, ARG_AREA }, { "area", required_argument, NULL, ARG_AREA },
{ "empower", no_argument, NULL, ARG_EMPOWER }, { "empower", no_argument, NULL, ARG_EMPOWER },
{ "same-root-dir", no_argument, NULL, ARG_SAME_ROOT_DIR },
{}, {},
}; };
@ -1074,13 +1072,6 @@ static int parse_argv_sudo_mode(int argc, char *argv[]) {
arg_empower = true; arg_empower = true;
break; break;
case ARG_SAME_ROOT_DIR:
r = free_and_strdup_warn(&arg_root_directory, "/");
if (r < 0)
return r;
break;
case '?': case '?':
return -EINVAL; return -EINVAL;

View File

@ -116,8 +116,6 @@ int sd_event_set_watchdog(sd_event *e, int b);
int sd_event_get_watchdog(sd_event *e); int sd_event_get_watchdog(sd_event *e);
int sd_event_get_iteration(sd_event *e, uint64_t *ret); int sd_event_get_iteration(sd_event *e, uint64_t *ret);
int sd_event_set_signal_exit(sd_event *e, int b); int sd_event_set_signal_exit(sd_event *e, int b);
int sd_event_set_exit_on_idle(sd_event *e, int b);
int sd_event_get_exit_on_idle(sd_event *e);
sd_event_source* sd_event_source_ref(sd_event_source *s); sd_event_source* sd_event_source_ref(sd_event_source *s);
sd_event_source* sd_event_source_unref(sd_event_source *s); sd_event_source* sd_event_source_unref(sd_event_source *s);

View File

@ -527,9 +527,7 @@ TEST(cgroupid) {
fd2 = cg_cgroupid_open(fd, id); fd2 = cg_cgroupid_open(fd, id);
/* The kernel converts a bunch of errors to ESTALE in the open_by_handle_at() codepath so we treat if (ERRNO_IS_NEG_PRIVILEGE(fd2))
* it as missing privs but it could be absolutely anything really. */
if (ERRNO_IS_NEG_PRIVILEGE(fd2) || fd2 == -ESTALE)
log_notice("Skipping open-by-cgroup-id test because lacking privs."); log_notice("Skipping open-by-cgroup-id test because lacking privs.");
else if (ERRNO_IS_NEG_NOT_SUPPORTED(fd2)) else if (ERRNO_IS_NEG_NOT_SUPPORTED(fd2))
log_notice("Skipping open-by-cgroup-id test because syscall is missing or blocked."); log_notice("Skipping open-by-cgroup-id test because syscall is missing or blocked.");

View File

@ -8,7 +8,6 @@
#include "sd-id128.h" #include "sd-id128.h"
#include "alloc-util.h" #include "alloc-util.h"
#include "capability-util.h"
#include "fd-util.h" #include "fd-util.h"
#include "id128-util.h" #include "id128-util.h"
#include "path-util.h" #include "path-util.h"
@ -279,7 +278,7 @@ TEST(id128_at) {
ASSERT_OK(sd_id128_randomize(&id)); ASSERT_OK(sd_id128_randomize(&id));
ASSERT_OK(id128_write_at(tfd, "etc/machine-id", ID128_FORMAT_PLAIN, id)); ASSERT_OK(id128_write_at(tfd, "etc/machine-id", ID128_FORMAT_PLAIN, id));
if (have_effective_cap(CAP_DAC_OVERRIDE)) if (geteuid() == 0)
ASSERT_OK(id128_write_at(tfd, "etc/machine-id", ID128_FORMAT_PLAIN, id)); ASSERT_OK(id128_write_at(tfd, "etc/machine-id", ID128_FORMAT_PLAIN, id));
else else
ASSERT_ERROR(id128_write_at(tfd, "etc/machine-id", ID128_FORMAT_PLAIN, id), EACCES); ASSERT_ERROR(id128_write_at(tfd, "etc/machine-id", ID128_FORMAT_PLAIN, id), EACCES);

View File

@ -3,7 +3,6 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <unistd.h> #include <unistd.h>
#include "capability-util.h"
#include "process-util.h" #include "process-util.h"
#include "rm-rf.h" #include "rm-rf.h"
#include "string-util.h" #include "string-util.h"
@ -30,7 +29,6 @@ static void test_rm_rf_chmod_inner(void) {
ASSERT_OK_ERRNO(chmod(x, 0500)); ASSERT_OK_ERRNO(chmod(x, 0500));
ASSERT_OK_ERRNO(chmod(d, 0500)); ASSERT_OK_ERRNO(chmod(d, 0500));
if (!have_effective_cap(CAP_DAC_OVERRIDE))
ASSERT_ERROR(rm_rf(d, REMOVE_PHYSICAL), EACCES); ASSERT_ERROR(rm_rf(d, REMOVE_PHYSICAL), EACCES);
ASSERT_OK_ERRNO(access(d, F_OK)); ASSERT_OK_ERRNO(access(d, F_OK));