1

I need to redirect output from udevadm monitor to a named pipe. For that end I use the following command:

sudo socat -u SYSTEM:"udevadm monitor" PIPE:/tmp/test &

It works until a process reading from the pipe is interrupted and socat exists with a "Broken pipe" error, which is expected. However, when I list running processes it turns out that udevadm is still running.

$ ps -a
  PID TTY          TIME CMD
 3539 tty1     00:00:00 bash
 3619 tty2     00:00:00 bash
 3972 pts/0    00:00:00 ps
$ sudo socat -u SYSTEM:"udevadm monitor" PIPE:/tmp/test &
[1] 3973
$ ps -a
  PID TTY          TIME CMD
 3539 tty1     00:00:00 bash
 3619 tty2     00:00:00 bash
 3973 pts/0    00:00:00 sudo
 3974 pts/0    00:00:00 socat
 3975 pts/0    00:00:00 socat
 3976 pts/0    00:00:00 udevadm
 3977 pts/0    00:00:00 ps
$ cat /tmp/test
monitor will print the received events for:
UDEV - the event which udev sends out after rule processing
KERNEL - the kernel uevent

^C
$ 2020/06/01 12:36:06 socat[3974] E write(6, 0x1dfbc60, 147): Broken pipe

[1]+  Exit 1                  sudo socat -u SYSTEM:"udevadm monitor" PIPE:/tmp/test
$ ps -a
  PID TTY          TIME CMD
 3539 tty1     00:00:00 bash
 3619 tty2     00:00:00 bash
 3976 pts/0    00:00:00 udevadm
 3980 pts/0    00:00:00 ps
$

When I replaced udevadm monitor with yes (to simply feed a stream of data to the pipe), it died along with socat.

If I simply interrupt socat with kill command, udevadm perishes neatly.

If I kill parent bash process socat and udevadm die as well, so I tried wrapping udevadm with sh -c:

sudo socat -u SYSTEM:'sh -c \"udevadm monitor\"' PIPE:/tmp/test &

hoping that dying shell would kill udevadm, but to no avail.

I am aware, that orphaned process can be adopted by INIT, but it doesn't seem to be the case, because out of all processes only udevadm seems to cheat death like this. To sum up my experiments:

  1. Process tree bash->sudo->socat->udevadm - kill socat - all die
  2. Process tree bash->sudo->socat->udevadm - broken pipe - only udevadm lives on
  3. Process tree bash->sudo->socat->sh->udevadm - broken pipe - only udevadm lives on
  4. Process tree bash->sudo->socat->yes- broken pipe - all die
  5. Process tree bash->sudo->socat->udevadm - kill sudo - all die
  6. Process tree bash->sudo->socat->udevadm - kill bash - all die

The problem I really want to solve are lingering udevadm processes.

My preferred solution would be to udevadm die nicely along with other processes. Acceptable solution would be to have persistent pipe, which would not break when reading process dies.

Are there any options or settings I can pass either to socat or to udevadm to solve my problem?

If socat if a wrong tool for my ultimate objective to have udevadm output sent to a pipe, I am obviously open for suggestions.

1

It seems to use a little magic, but you can try inverting the two addresses so you can then add option nofork to the system command. You need to swap -u to -U of course to change direction:

socat -U PIPE:/tmp/test SYSTEM:"udevadm monitor",nofork

This seems to ignore the closing of the pipe, and you can re-open it again. Don't ask me about the magic.

| improve this answer | |
  • This works very nicely, and the pipe it creates a pipe which survives not only reader's death, but even creator's death. I like it, thank you :) But I'll be honest, I wish I knew how the magic works, cargo cult is hardly a sound engineering practice ;) – Darth Hunterix Jun 2 at 6:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.