mirror of
https://github.com/systemd/systemd.git
synced 2024-11-27 20:23:36 +08:00
2fa480592d
When an IO event source owns relevant fd, replacing with a new fd leaks the previously assigned fd. === sd_event_add_io(event, &s, fd, ...); sd_event_source_set_io_fd_own(s, true); sd_event_source_set_io_fd(s, new_fd); <-- The previous fd is not closed. sd_event_source_unref(s); <-- new_fd is closed as expected. === Without the change, valgrind reports the leak: ==998589== ==998589== FILE DESCRIPTORS: 4 open (3 std) at exit. ==998589== Open file descriptor 4: ==998589== at 0x4F119AB: pipe2 (in /usr/lib64/libc.so.6) ==998589== by 0x408830: test_sd_event_source_set_io_fd (test-event.c:862) ==998589== by 0x403302: run_test_table (tests.h:171) ==998589== by 0x408E31: main (test-event.c:935) ==998589== ==998589== ==998589== HEAP SUMMARY: ==998589== in use at exit: 0 bytes in 0 blocks ==998589== total heap usage: 33,305 allocs, 33,305 frees, 1,283,581 bytes allocated ==998589== ==998589== All heap blocks were freed -- no leaks are possible ==998589== ==998589== For lists of detected and suppressed errors, rerun with: -s ==998589== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
340 lines
18 KiB
XML
340 lines
18 KiB
XML
<?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_add_io" xmlns:xi="http://www.w3.org/2001/XInclude">
|
|
|
|
<refentryinfo>
|
|
<title>sd_event_add_io</title>
|
|
<productname>systemd</productname>
|
|
</refentryinfo>
|
|
|
|
<refmeta>
|
|
<refentrytitle>sd_event_add_io</refentrytitle>
|
|
<manvolnum>3</manvolnum>
|
|
</refmeta>
|
|
|
|
<refnamediv>
|
|
<refname>sd_event_add_io</refname>
|
|
<refname>sd_event_source_get_io_events</refname>
|
|
<refname>sd_event_source_set_io_events</refname>
|
|
<refname>sd_event_source_get_io_revents</refname>
|
|
<refname>sd_event_source_get_io_fd</refname>
|
|
<refname>sd_event_source_set_io_fd</refname>
|
|
<refname>sd_event_source_get_io_fd_own</refname>
|
|
<refname>sd_event_source_set_io_fd_own</refname>
|
|
<refname>sd_event_source</refname>
|
|
<refname>sd_event_io_handler_t</refname>
|
|
|
|
<refpurpose>Add an I/O event source to an event loop</refpurpose>
|
|
</refnamediv>
|
|
|
|
<refsynopsisdiv>
|
|
<funcsynopsis>
|
|
<funcsynopsisinfo>#include <systemd/sd-event.h></funcsynopsisinfo>
|
|
|
|
<funcsynopsisinfo><token>typedef</token> struct sd_event_source sd_event_source;</funcsynopsisinfo>
|
|
|
|
<funcprototype>
|
|
<funcdef>typedef int (*<function>sd_event_io_handler_t</function>)</funcdef>
|
|
<paramdef>sd_event_source *<parameter>s</parameter></paramdef>
|
|
<paramdef>int <parameter>fd</parameter></paramdef>
|
|
<paramdef>uint32_t <parameter>revents</parameter></paramdef>
|
|
<paramdef>void *<parameter>userdata</parameter></paramdef>
|
|
</funcprototype>
|
|
|
|
<funcprototype>
|
|
<funcdef>int <function>sd_event_add_io</function></funcdef>
|
|
<paramdef>sd_event *<parameter>event</parameter></paramdef>
|
|
<paramdef>sd_event_source **<parameter>source</parameter></paramdef>
|
|
<paramdef>int <parameter>fd</parameter></paramdef>
|
|
<paramdef>uint32_t <parameter>events</parameter></paramdef>
|
|
<paramdef>sd_event_io_handler_t <parameter>handler</parameter></paramdef>
|
|
<paramdef>void *<parameter>userdata</parameter></paramdef>
|
|
</funcprototype>
|
|
|
|
<funcprototype>
|
|
<funcdef>int <function>sd_event_source_get_io_events</function></funcdef>
|
|
<paramdef>sd_event_source *<parameter>source</parameter></paramdef>
|
|
<paramdef>uint32_t *<parameter>events</parameter></paramdef>
|
|
</funcprototype>
|
|
|
|
<funcprototype>
|
|
<funcdef>int <function>sd_event_source_set_io_events</function></funcdef>
|
|
<paramdef>sd_event_source *<parameter>source</parameter></paramdef>
|
|
<paramdef>uint32_t <parameter>events</parameter></paramdef>
|
|
</funcprototype>
|
|
|
|
<funcprototype>
|
|
<funcdef>int <function>sd_event_source_get_io_revents</function></funcdef>
|
|
<paramdef>sd_event_source *<parameter>source</parameter></paramdef>
|
|
<paramdef>uint32_t *<parameter>revents</parameter></paramdef>
|
|
</funcprototype>
|
|
|
|
<funcprototype>
|
|
<funcdef>int <function>sd_event_source_get_io_fd</function></funcdef>
|
|
<paramdef>sd_event_source *<parameter>source</parameter></paramdef>
|
|
</funcprototype>
|
|
|
|
<funcprototype>
|
|
<funcdef>int <function>sd_event_source_set_io_fd</function></funcdef>
|
|
<paramdef>sd_event_source *<parameter>source</parameter></paramdef>
|
|
<paramdef>int <parameter>fd</parameter></paramdef>
|
|
</funcprototype>
|
|
|
|
<funcprototype>
|
|
<funcdef>int <function>sd_event_source_get_io_fd_own</function></funcdef>
|
|
<paramdef>sd_event_source *<parameter>source</parameter></paramdef>
|
|
</funcprototype>
|
|
|
|
<funcprototype>
|
|
<funcdef>int <function>sd_event_source_set_io_fd_own</function></funcdef>
|
|
<paramdef>sd_event_source *<parameter>source</parameter></paramdef>
|
|
<paramdef>int <parameter>b</parameter></paramdef>
|
|
</funcprototype>
|
|
|
|
</funcsynopsis>
|
|
</refsynopsisdiv>
|
|
|
|
<refsect1>
|
|
<title>Description</title>
|
|
|
|
<para><function>sd_event_add_io()</function> adds a new I/O event source to an event loop. The event loop
|
|
object is specified in the <parameter>event</parameter> parameter, the event source object is returned in
|
|
the <parameter>source</parameter> parameter. The <parameter>fd</parameter> parameter takes the UNIX file
|
|
descriptor to watch, which may refer to a socket, a FIFO, a message queue, a serial connection, a
|
|
character device, or any other file descriptor compatible with Linux <citerefentry
|
|
project='man-pages'><refentrytitle>epoll</refentrytitle><manvolnum>7</manvolnum></citerefentry>. The
|
|
<parameter>events</parameter> parameter takes a bit mask of events to watch for, a combination of the
|
|
following event flags: <constant>EPOLLIN</constant>, <constant>EPOLLOUT</constant>,
|
|
<constant>EPOLLRDHUP</constant>, <constant>EPOLLPRI</constant>, and <constant>EPOLLET</constant>, see
|
|
<citerefentry
|
|
project='man-pages'><refentrytitle>epoll_ctl</refentrytitle><manvolnum>2</manvolnum></citerefentry> for
|
|
details. Note that not all file descriptors are compatible with epoll, for example regular file or
|
|
directories are not. If this function is called with a file descriptor that does not support epoll,
|
|
<constant>-EPERM</constant> is returned (also see below). In most cases such file descriptors may be
|
|
treated as always-readable or always-writable, so that IO event watching is unnecessary.</para>
|
|
|
|
<para>The <parameter>handler</parameter> is a function to call when the event source is triggered or
|
|
<constant>NULL</constant>. The <parameter>userdata</parameter> pointer will be passed to the handler
|
|
function, and may be chosen freely by the caller. The handler will also be passed the file descriptor the
|
|
event was seen on, as well as the actual event flags. It's generally a subset of the events watched,
|
|
however may additionally include <constant>EPOLLERR</constant> and <constant>EPOLLHUP</constant>. The
|
|
handler may return negative to signal an error (see below), other return values are ignored. If
|
|
<parameter>handler</parameter> is <constant>NULL</constant>, a default handler that calls
|
|
<citerefentry><refentrytitle>sd_event_exit</refentrytitle><manvolnum>3</manvolnum></citerefentry> will be
|
|
used.</para>
|
|
|
|
<para>By default, an event source will stay enabled continuously (<constant>SD_EVENT_ON</constant>), but
|
|
this may be changed with
|
|
<citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
|
|
If the handler function returns a negative error code, it will either be disabled after the invocation,
|
|
even if the <constant>SD_EVENT_ON</constant> mode was requested before, or it will cause the loop to
|
|
terminate, see
|
|
<citerefentry><refentrytitle>sd_event_source_set_exit_on_failure</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
|
|
Note that an event source set to <constant>SD_EVENT_ON</constant> will fire continuously unless data is
|
|
read from or written to the file descriptor to reset the mask of events seen.</para>
|
|
|
|
<para>Setting the I/O event mask to watch for to 0 does not mean
|
|
that the event source won't be triggered anymore, as
|
|
<constant>EPOLLHUP</constant> and <constant>EPOLLERR</constant>
|
|
may be triggered even with a zero event mask. To temporarily
|
|
disable an I/O event source use
|
|
<citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>
|
|
with <constant>SD_EVENT_OFF</constant> instead.</para>
|
|
|
|
<para>To destroy an event source object use
|
|
<citerefentry><refentrytitle>sd_event_source_unref</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
|
but note that the event source is only removed from the event loop
|
|
when all references to the event source are dropped. To make sure
|
|
an event source does not fire anymore, even if it is still referenced,
|
|
disable the event source using
|
|
<citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>
|
|
with <constant>SD_EVENT_OFF</constant>.</para>
|
|
|
|
<para>If the second parameter of
|
|
<function>sd_event_add_io()</function> is
|
|
<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> 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
|
|
take ownership of the file descriptor after the event source has been created. In that case the file
|
|
descriptor is closed automatically as soon as the event source is released.</para>
|
|
|
|
<para>It is recommended to use
|
|
<function>sd_event_add_io()</function> only in conjunction with
|
|
file descriptors that have <constant>O_NONBLOCK</constant> set, to
|
|
ensure that all I/O operations from invoked handlers are properly
|
|
asynchronous and non-blocking. Using file descriptors without
|
|
<constant>O_NONBLOCK</constant> might result in unexpected
|
|
starvation of other event sources. See
|
|
<citerefentry project='man-pages'><refentrytitle>fcntl</refentrytitle><manvolnum>2</manvolnum></citerefentry>
|
|
for details on enabling <constant>O_NONBLOCK</constant> mode.</para>
|
|
|
|
<para><function>sd_event_source_get_io_events()</function> retrieves
|
|
the configured mask of watched I/O events of an event source created
|
|
previously with <function>sd_event_add_io()</function>. It takes
|
|
the event source object and a pointer to a variable to store the
|
|
mask in.</para>
|
|
|
|
<para><function>sd_event_source_set_io_events()</function>
|
|
configures the mask of watched I/O events of an event source created
|
|
previously with <function>sd_event_add_io()</function>. It takes the
|
|
event source object and the new event mask.</para>
|
|
|
|
<para><function>sd_event_source_get_io_revents()</function>
|
|
retrieves the I/O event mask of currently seen but undispatched
|
|
events from an event source created previously with
|
|
<function>sd_event_add_io()</function>. It takes the event source
|
|
object and a pointer to a variable to store the event mask
|
|
in. When called from a handler function on the handler's event
|
|
source object this will return the same mask as passed to the
|
|
handler's <parameter>revents</parameter> parameter. This call is
|
|
primarily useful to check for undispatched events of an event
|
|
source from the handler of an unrelated (possibly higher priority)
|
|
event source. Note the relation between
|
|
<function>sd_event_source_get_pending()</function> and
|
|
<function>sd_event_source_get_io_revents()</function>: both
|
|
functions will report non-zero results when there's an event
|
|
pending for the event source, but the former applies to all event
|
|
source types, the latter only to I/O event sources.</para>
|
|
|
|
<para><function>sd_event_source_get_io_fd()</function> retrieves
|
|
the UNIX file descriptor of an event source created previously
|
|
with <function>sd_event_add_io()</function>. It takes the event
|
|
source object and returns the non-negative file descriptor
|
|
or a negative error number on error (see below).</para>
|
|
|
|
<para><function>sd_event_source_set_io_fd()</function> changes the UNIX file descriptor of an I/O event
|
|
source created previously with <function>sd_event_add_io()</function>. It takes the event source object
|
|
and the new file descriptor. If the event source takes the ownership of the previous file descriptor,
|
|
that is, <function>sd_event_source_set_io_fd_own()</function> was called for the event source with a
|
|
non-zero value, then the previous file descriptor will be closed and the event source will also take the
|
|
ownership of the new file descriptor on success.</para>
|
|
|
|
<para><function>sd_event_source_set_io_fd_own()</function> controls whether the file descriptor of the
|
|
event source shall be closed automatically when the event source is freed (or when the file descriptor
|
|
assigned to the event source is replaced by <function>sd_event_source_set_io_fd()</function>), i.e.
|
|
whether it shall be considered 'owned' by the event source object. By default it is not closed
|
|
automatically, and the application has to do this on its own. The <parameter>b</parameter> parameter is a
|
|
boolean parameter: if zero, the file descriptor is not closed automatically when the event source is
|
|
freed, otherwise it is closed.</para>
|
|
|
|
<para><function>sd_event_source_get_io_fd_own()</function> may be used to query the current setting of the file
|
|
descriptor ownership boolean flag as set with <function>sd_event_source_set_io_fd_own()</function>. It returns
|
|
positive if the file descriptor is closed automatically when the event source is destroyed, zero if not, and
|
|
negative on error.</para>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Return Value</title>
|
|
|
|
<para>On success, these functions return 0 or a positive
|
|
integer. On failure, they return a negative errno-style error
|
|
code.</para>
|
|
|
|
<refsect2>
|
|
<title>Errors</title>
|
|
|
|
<para>Returned values may indicate the following problems:</para>
|
|
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><constant>-ENOMEM</constant></term>
|
|
|
|
<listitem><para>Not enough memory to allocate an object.</para></listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><constant>-EINVAL</constant></term>
|
|
|
|
<listitem><para>An invalid argument has been passed.</para></listitem>
|
|
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><constant>-ESTALE</constant></term>
|
|
|
|
<listitem><para>The event loop is already terminated.</para></listitem>
|
|
|
|
</varlistentry>
|
|
|
|
<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>-EDOM</constant></term>
|
|
|
|
<listitem><para>The passed event source is not an I/O event source.</para></listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><constant>-EPERM</constant></term>
|
|
|
|
<listitem><para>The passed file descriptor does not support the <citerefentry
|
|
project='man-pages'><refentrytitle>epoll</refentrytitle><manvolnum>7</manvolnum></citerefentry>
|
|
API, for example because it is a regular file or directory. See <citerefentry
|
|
project='man-pages'><refentrytitle>epoll_ctl</refentrytitle><manvolnum>2</manvolnum></citerefentry>
|
|
for details.</para>
|
|
|
|
<xi:include href="version-info.xml" xpointer="v255"/></listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</refsect2>
|
|
</refsect1>
|
|
|
|
<xi:include href="libsystemd-pkgconfig.xml" />
|
|
|
|
<refsect1>
|
|
<title>History</title>
|
|
<para><function>sd_event_io_handler_t()</function>,
|
|
<function>sd_event_add_io()</function>,
|
|
<function>sd_event_source_get_io_events()</function>,
|
|
<function>sd_event_source_set_io_events()</function>,
|
|
<function>sd_event_source_get_io_revents()</function>,
|
|
<function>sd_event_source_get_io_fd()</function>, and
|
|
<function>sd_event_source_set_io_fd()</function> were added in version 229.</para>
|
|
<para><function>sd_event_source_get_io_fd_own()</function> and
|
|
<function>sd_event_source_set_io_fd_own()</function> were added in version 239.</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_now</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>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry></member>
|
|
<member><citerefentry><refentrytitle>sd_event_source_set_priority</refentrytitle><manvolnum>3</manvolnum></citerefentry></member>
|
|
<member><citerefentry><refentrytitle>sd_event_source_set_userdata</refentrytitle><manvolnum>3</manvolnum></citerefentry></member>
|
|
<member><citerefentry><refentrytitle>sd_event_source_set_description</refentrytitle><manvolnum>3</manvolnum></citerefentry></member>
|
|
<member><citerefentry><refentrytitle>sd_event_source_get_pending</refentrytitle><manvolnum>3</manvolnum></citerefentry></member>
|
|
<member><citerefentry><refentrytitle>sd_event_source_set_floating</refentrytitle><manvolnum>3</manvolnum></citerefentry></member>
|
|
<member><citerefentry project='man-pages'><refentrytitle>epoll_ctl</refentrytitle><manvolnum>2</manvolnum></citerefentry></member>
|
|
<member><citerefentry project='man-pages'><refentrytitle>epoll</refentrytitle><manvolnum>7</manvolnum></citerefentry></member>
|
|
</simplelist></para>
|
|
</refsect1>
|
|
|
|
</refentry>
|