• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

systemd / systemd / 25026908423

27 Apr 2026 07:14PM UTC coverage: 71.865% (-0.3%) from 72.175%
25026908423

push

github

daandemeyer
udev: don't assert on worker cap after killing a broken idle worker

manager_can_process_event() considers an event processable if either
there is room below children_max to spawn, or an idle worker exists.
When only the latter holds, event_run() picks the idle worker and
tries device_monitor_send(). If that send fails, event_run() SIGKILLs
the worker, marks it WORKER_KILLED and continues the loop. With no
other idle worker available, it falls through to worker_spawn(),
guarded by:

    assert(hashmap_size(manager->workers) < manager->config.children_max);

The just-killed worker is still in manager->workers until its SIGCHLD
is reaped by on_worker_exit(), so at the cap this assertion trips and
udevd aborts:

    Assertion 'hashmap_size(manager->workers) < manager->config.children_max'
    failed at src/udev/udev-manager.c:635, function event_run(). Aborting.

Instead of asserting, bail out when we are already at the worker
limit. The event remains in EVENT_QUEUED; once the killed worker's
SIGCHLD arrives and frees it from the hashmap, on_post() re-runs
event_queue_start() and the event is retried.

1 of 1 new or added line in 1 file covered. (100.0%)

7309 existing lines in 125 files now uncovered.

322519 of 448782 relevant lines covered (71.87%)

1173939.78 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

77.03
/src/basic/io-util.c
1
/* SPDX-License-Identifier: LGPL-2.1-or-later */
2

3
#include <poll.h>
4
#include <stdio.h>
5
#include <string.h>
6
#include <time.h>
7
#include <unistd.h>
8

9
#include "errno-util.h"
10
#include "io-util.h"
11
#include "time-util.h"
12

13
int flush_fd(int fd) {
3,931✔
14
        int count = 0;
3,931✔
15

16
        /* Read from the specified file descriptor, until POLLIN is not set anymore, throwing away everything
17
         * read. Note that some file descriptors (notable IP sockets) will trigger POLLIN even when no data can be read
18
         * (due to IP packet checksum mismatches), hence this function is only safe to be non-blocking if the fd used
19
         * was set to non-blocking too. */
20

21
        for (;;) {
7,390✔
22
                char buf[LINE_MAX];
7,390✔
23
                ssize_t l;
7,390✔
24
                int r;
7,390✔
25

26
                r = fd_wait_for_event(fd, POLLIN, 0);
7,390✔
27
                if (r == -EINTR)
7,390✔
28
                        continue;
×
29
                if (r < 0)
7,390✔
30
                        return r;
3,931✔
31
                if (r == 0)
7,390✔
32
                        return count;
33

34
                l = read(fd, buf, sizeof(buf));
3,459✔
35
                if (l < 0) {
3,459✔
36
                        if (errno == EINTR)
×
37
                                continue;
×
38
                        if (errno == EAGAIN)
×
39
                                return count;
40

41
                        return -errno;
×
42
                } else if (l == 0)
3,459✔
43
                        return count;
44

45
                if (l > INT_MAX-count) /* On overflow terminate */
3,459✔
46
                        return INT_MAX;
47

48
                count += (int) l;
3,459✔
49
        }
50
}
51

52
ssize_t loop_read(int fd, void *buf, size_t nbytes, bool do_poll) {
18,154✔
53
        uint8_t *p = ASSERT_PTR(buf);
18,154✔
54
        ssize_t n = 0;
18,154✔
55

56
        assert(fd >= 0);
18,154✔
57

58
        /* If called with nbytes == 0, let's call read() at least once, to validate the operation */
59

60
        if (nbytes > (size_t) SSIZE_MAX)
18,154✔
61
                return -EINVAL;
62

63
        do {
31,752✔
64
                ssize_t k;
31,752✔
65

66
                k = read(fd, p, nbytes);
31,752✔
67
                if (k < 0) {
31,752✔
68
                        if (errno == EINTR)
×
69
                                continue;
×
70

71
                        if (errno == EAGAIN && do_poll) {
×
72

73
                                /* We knowingly ignore any return value here,
74
                                 * and expect that any error/EOF is reported
75
                                 * via read() */
76

77
                                (void) fd_wait_for_event(fd, POLLIN, USEC_INFINITY);
×
78
                                continue;
×
79
                        }
80

81
                        return n > 0 ? n : -errno;
×
82
                }
83

84
                if (k == 0)
31,752✔
85
                        return n;
86

87
                assert((size_t) k <= nbytes);
17,947✔
88
                assert(k <= SSIZE_MAX - n);
17,947✔
89

90
                p += k;
17,947✔
91
                nbytes -= k;
17,947✔
92
                n += k;
17,947✔
93
        } while (nbytes > 0);
17,947✔
94

95
        return n;
96
}
97

98
int loop_read_exact(int fd, void *buf, size_t nbytes, bool do_poll) {
3,991✔
99
        ssize_t n;
3,991✔
100

101
        n = loop_read(fd, buf, nbytes, do_poll);
3,991✔
102
        if (n < 0)
3,991✔
103
                return (int) n;
×
104
        if ((size_t) n != nbytes)
3,991✔
105
                return -EIO;
×
106

107
        return 0;
108
}
109

110
int loop_write_full(int fd, const void *buf, size_t nbytes, usec_t timeout) {
25,279✔
111
        const uint8_t *p;
25,279✔
112
        usec_t end;
25,279✔
113
        int r;
25,279✔
114

115
        assert(fd >= 0);
25,279✔
116
        assert(buf || nbytes == 0);
25,279✔
117

118
        if (nbytes == 0) {
25,279✔
119
                static const dummy_t dummy[0];
120
                assert_cc(sizeof(dummy) == 0);
121
                p = (const void*) dummy; /* Some valid pointer, in case NULL was specified */
122
        } else {
123
                if (nbytes == SIZE_MAX)
25,278✔
124
                        nbytes = strlen(buf);
349✔
125
                else if (_unlikely_(nbytes > (size_t) SSIZE_MAX))
24,929✔
126
                        return -EINVAL;
127

128
                p = buf;
129
        }
130

131
        /* When timeout is 0 or USEC_INFINITY this is not used. But we initialize it to a sensible value. */
132
        end = timestamp_is_set(timeout) ? usec_add(now(CLOCK_MONOTONIC), timeout) : USEC_INFINITY;
25,333✔
133

134
        do {
25,279✔
135
                ssize_t k;
25,279✔
136

137
                k = write(fd, p, nbytes);
25,279✔
138
                if (k < 0) {
25,279✔
139
                        if (errno == EINTR)
1✔
140
                                continue;
×
141

142
                        if (errno != EAGAIN || timeout == 0)
1✔
143
                                return -errno;
1✔
144

145
                        usec_t wait_for;
×
146

147
                        if (timeout == USEC_INFINITY)
×
148
                                wait_for = USEC_INFINITY;
149
                        else {
150
                                usec_t t = now(CLOCK_MONOTONIC);
×
151
                                if (t >= end)
×
152
                                        return -ETIME;
153

154
                                wait_for = usec_sub_unsigned(end, t);
×
155
                        }
156

157
                        r = fd_wait_for_event(fd, POLLOUT, wait_for);
×
158
                        if (timeout == USEC_INFINITY || ERRNO_IS_NEG_TRANSIENT(r))
×
159
                                /* If timeout == USEC_INFINITY we knowingly ignore any return value
160
                                 * here, and expect that any error/EOF is reported via write() */
161
                                continue;
×
162
                        if (r < 0)
×
163
                                return r;
164
                        if (r == 0)
×
165
                                return -ETIME;
166
                        continue;
×
167
                }
168

169
                if (_unlikely_(nbytes > 0 && k == 0)) /* Can't really happen */
25,278✔
170
                        return -EIO;
171

172
                assert((size_t) k <= nbytes);
25,278✔
173

174
                p += k;
25,278✔
175
                nbytes -= k;
25,278✔
176
        } while (nbytes > 0);
25,278✔
177

178
        return 0;
179
}
180

181
int pipe_eof(int fd) {
×
182
        int r;
×
183

184
        r = fd_wait_for_event(fd, POLLIN, 0);
×
185
        if (r <= 0)
×
186
                return r;
187

188
        return !!(r & POLLHUP);
×
189
}
190

191
int ppoll_usec_full(struct pollfd *fds, size_t n_fds, usec_t timeout, const sigset_t *ss) {
606,811✔
192
        int r;
606,811✔
193

194
        assert(fds || n_fds == 0);
606,811✔
195

196
        /* This is a wrapper around ppoll() that does primarily two things:
197
         *
198
         *  ✅ Takes a usec_t instead of a struct timespec
199
         *
200
         *  ✅ Guarantees that if an invalid fd is specified we return EBADF (i.e. converts POLLNVAL to
201
         *     EBADF). This is done because EBADF is a programming error usually, and hence should bubble up
202
         *     as error, and not be eaten up as non-error POLLNVAL event.
203
         *
204
         *  ⚠️ ⚠️ ⚠️ Note that this function does not add any special handling for EINTR. Don't forget
205
         *  poll()/ppoll() will return with EINTR on any received signal always, there is no automatic
206
         *  restarting via SA_RESTART available. Thus, typically you want to handle EINTR not as an error,
207
         *  but just as reason to restart things, under the assumption you use a more appropriate mechanism
208
         *  to handle signals, such as signalfd() or signal handlers. ⚠️ ⚠️ ⚠️
209
         */
210

211
        if (n_fds == 0 && timeout == 0)
606,811✔
212
                return 0;
606,811✔
213

214
        r = ppoll(fds, n_fds, timeout == USEC_INFINITY ? NULL : TIMESPEC_STORE(timeout), ss);
606,811✔
215
        if (r < 0)
606,811✔
UNCOV
216
                return -errno;
×
217
        if (r == 0)
606,811✔
218
                return 0;
219

220
        for (size_t i = 0, n = r; i < n_fds && n > 0; i++) {
1,112,678✔
221
                if (fds[i].revents == 0)
557,213✔
222
                        continue;
1,660✔
223
                if (fds[i].revents & POLLNVAL)
555,553✔
224
                        return -EBADF;
225
                n--;
555,553✔
226
        }
227

228
        return r;
229
}
230

231
int fd_wait_for_event(int fd, int event, usec_t timeout) {
70,395✔
232
        struct pollfd pollfd = {
70,395✔
233
                .fd = fd,
234
                .events = event,
235
        };
236
        int r;
70,395✔
237

238
        /* ⚠️ ⚠️ ⚠️ Keep in mind you almost certainly want to handle -EINTR gracefully in the caller, see
239
         * ppoll_usec() above! ⚠️ ⚠️ ⚠️ */
240

241
        r = ppoll_usec(&pollfd, 1, timeout);
70,395✔
242
        if (r <= 0)
70,395✔
243
                return r;
70,395✔
244

245
        return pollfd.revents;
19,054✔
246
}
247

248
static size_t nul_length(const uint8_t *p, size_t sz) {
293,651,346✔
249
        size_t n = 0;
293,651,346✔
250

251
        assert(p);
293,651,346✔
252

253
        while (sz > 0) {
858,680,927✔
254
                if (*p != 0)
858,676,320✔
255
                        break;
256

257
                n++;
565,029,581✔
258
                p++;
565,029,581✔
259
                sz--;
565,029,581✔
260
        }
261

262
        return n;
293,651,346✔
263
}
264

265
ssize_t sparse_write(int fd, const void *p, size_t sz, size_t run_length) {
6,547✔
266
        const uint8_t *q, *w, *e;
6,547✔
267
        ssize_t l;
6,547✔
268

269
        q = w = p;
6,547✔
270
        e = q + sz;
6,547✔
271
        while (q < e) {
293,657,893✔
272
                size_t n;
293,651,346✔
273

274
                n = nul_length(q, e - q);
293,651,346✔
275

276
                /* If there are more than the specified run length of
277
                 * NUL bytes, or if this is the beginning or the end
278
                 * of the buffer, then seek instead of write */
279
                if ((n > run_length) ||
293,651,346✔
280
                    (n > 0 && q == p) ||
293,472,527✔
281
                    (n > 0 && q + n >= e)) {
20,839,810✔
282
                        if (q > w) {
179,879✔
283
                                l = write(fd, w, q - w);
175,850✔
284
                                if (l < 0)
175,850✔
285
                                        return -errno;
×
286
                                if (l != q -w)
175,850✔
287
                                        return -EIO;
288
                        }
289

290
                        if (lseek(fd, n, SEEK_CUR) < 0)
179,879✔
291
                                return -errno;
×
292

293
                        q += n;
179,879✔
294
                        w = q;
179,879✔
295
                } else if (n > 0)
20,839,082✔
296
                        q += n;
297
                else
298
                        q++;
272,632,385✔
299
        }
300

301
        if (q > w) {
6,547✔
302
                l = write(fd, w, q - w);
1,940✔
303
                if (l < 0)
1,940✔
304
                        return -errno;
×
305
                if (l != q - w)
1,940✔
306
                        return -EIO;
307
        }
308

309
        return q - (const uint8_t*) p;
6,547✔
310
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc