On Wed, 2008-10-22 at 15:10 +0100, Alan Jenkins wrote: > == Justification for udev-exec == > > External programs are run from a "udev-exec" subprocess. This was > measured as reducing the fork() overhead. To reduce overheads further, > it allowed me to use of vfork() without temporarily suspending all the > threads. The commands to run are passed over a unix datagram socket; > pipes for stdout / stderr pipes are passed as ancillary data. This > udev-exec accounts for over half the code. The message passing > shouldn't impose too much overhead. I think udev-exec should be used > even if threading has been disabled, otherwise there would be too many > ugly #ifdefs. > This sounds odd to me; udev-exec still needs to fork() for each child, and there's a cost of passing the command over the socket -- so how is this cheaper than just fork()ing inside udevd? > udev-exec also avoids running external programs with extra file > descriptors - the problem "close on exec" was designed to solve. I > don't think I could insist on a kernel recent enough to provide "close > on exec" support. Plus I don't think "close on exec" helps with pipes > used to communicate with child processes. Without this, the Ubuntu > "watershed" command seemed to complain about extra file descriptors. > I see no problem with depending on the very latest kernels; using a latest udev version goes hand-in-hand with using a latest kernel. The pipe2() syscall allows you to specify flags for the returned file descriptors: pipe2 (&fds, O_CLOEXEC) > Lastly, udev-exec helped with implementing timeouts - event threads just > call select() with a timeout, waiting to read the exitcode of the > command from a pipe. None of the wait() family of commands include a > timeout. alarm() wouldn't work because it's per-process. Without > udev-exec, I would have to create posix timers with callbacks to signal > the correct thread - and disable SA_RESTART before waiting. > Ironically, I have a long-standing proposal to fix this ;) I've just got to get around to persuading a kernel developer to do it, or do it myself. The idea was you'd do: fd = waitfd (P_PID, pid, 0); FD_SET (fd, &readfds); select (fd + 1, &readfds, NULL, NULL, &timeout); read (fd, &siginfo, sizeof (struct siginfo_t)); ie. a version of waitid() that returns the data through a socket - then all daemon main loop events could be done with select() [we already have signalfd(), timerfd_*(), etc.) Scott -- Scott James Remnant scott@xxxxxxxxxxxxx
Attachment:
signature.asc
Description: This is a digitally signed message part