Skip to contentSkip to conversation

udevd move from select() to ppoll()

DISCUSSION Coleman Kane 2 participants 2 messages May 13, 2009 – May 14, 2009

lore
Share & tools
lore
#0 lore raw

Hi,

I'm writing as I recently encountered a regression after the select() --> ppoll() move in the udevd daemon, running on uClibc-0.9.29 and at least kernels since 2.6.28.

For some reason the ppoll call always returns -1 w/ EINVAL in this configuration. I actually anticipate this to be a bug in either Linux or uClibc...

However, while investigating this, I came across the following sequence of steps performed in udevd.c (line 973):

fdcount = ppoll(pfd, nfds, NULL, &orig_mask);
sigprocmask(SIG_SETMASK, &orig_mask, NULL);

Maybe I am missing something, but my reading of the man page indicates that the following sequence would accomplish the same work, but would be faster, as it eliminates the restoration of blocked_mask at the end of the ppoll() call, which then proceeds to be overwritten again to what it was inside ppoll by the above sigprocmask() call.

Would it be basically the same to do the following (but faster)?

sigprocmask(SIG_SETMASK, &orig_mask, NULL);
fdcount = poll(pfd, nfds, -1);

Additionally, this reportedly fixes the EINVAL that is hit in uClibc too, which doesn't reach the error condition in poll().

Signature · 1 line
Coleman Kane
#1 lore raw
Quoted 3 lines · Coleman Kane

For some reason the ppoll call always returns -1 w/ EINVAL in this configuration. I actually anticipate this to be a bug in either Linux or uClibc...

Likely the libc, I did not hear of any such problems somewhere else. What does strace show?

Quoted 12 lines

However, while investigating this, I came across the following sequence of steps performed in udevd.c (line 973):

fdcount = ppoll(pfd, nfds, NULL, &orig_mask);
sigprocmask(SIG_SETMASK, &orig_mask, NULL);

Maybe I am missing something, but my reading of the man page indicates that the following sequence would accomplish the same work, but would be faster, as it eliminates the restoration of blocked_mask at the end of the ppoll() call, which then proceeds to be overwritten again to what it was inside ppoll by the above sigprocmask() call.

Quoted 4 lines

Would it be basically the same to do the following (but faster)?

sigprocmask(SIG_SETMASK, &orig_mask, NULL);
fdcount = poll(pfd, nfds, -1);

If signals happen between this sigprocmask() and the poll(), you go to sleep, even when you need to do work. The use of ppoll() is just the same sequence of operations, but done atomically in the kernel, which prevents the mentioned race.

Kay