See what processes share a pipe and what goes through

This is part of the Semicolon&Sons Code Diary - consisting of lessons learned on the job. You're in the unix category.

Last Updated: 2024-04-25

Given the PID of a process with a pipe, run $ lsof -p $PID. Some of the output will have a column PIPE.

Python  3636 jack    2u  unix 0xa450889cddebc233      0t0            ->0xa450889cddebc7ab
Python  3636 jack    4   PIPE 0xa450889cdbfdba7b    16384            ->0xa450889cdbfd9a3b

Now grep the output of system wide lsof (i.e. unconstrained to one pid) for that memory address associated with the pipe:

lsof -n -P | grep 0xa450889cdbfdba7b
Python     3636 jack    4      PIPE 0xa450889cdbfdba7b      16384            ->0xa450889cdbfd9a3b
Python     4932 jack    0      PIPE 0xa450889cdbfd9a3b      16384            ->0xa450889cdbfdba7b

Ah ha, process 4932 is the other end of that pipe!

For the next step, on macos at least, we need dtruss. Its full features are disabled due to System Integrity Protection, so boot in recovery mode (Command + R on startup) and disable just for dstruss: csrutil enable --without dtrace

After restarting, run $ sudo dtruss -p 3636 . Sure enough, I see the function signatures in dtruss

stat64("/private/tmp/baby-py/product.py\0", 0x7FFEE1EE7F10, 0x0)         = 0 0
open("/private/tmp/baby-py/product.py\0", 0x1000000, 0x1B6)      = 4 0
fstat64(0x4, 0x7FFEE1EE8528, 0x0)        = 0 0
lseek(0x4, 0x0, 0x1)         = 0 0
fstat64(0x4, 0x7FFEE1EE8510, 0x0)        = 0 0
read(0x4, "def sales():\n    return 22\n\035\374\r\001\214\022is_allowed_getattr\224\214\005Fa

You might say there is too much info there — so how about limiting what is seen to write calls?

$ sudo dtruss -p 3728 -f -t write
3728/0x55df:  write(0x1, "Content-Length: 2087\r\nContent-Type: application/vscode-jsonrpc; charset=utf8\r\n\r\n{\"jsonrpc\":\"2.0\",\"id\":79,\"result\":{\"isIncomplete\":false,\"items\":[{\"label\":\"abc\",\"kind\":9,\"detail\":\"abc\",\"documentation\":\"\",\"sortText\":\"aabc\",\"insertText\":\"abc\"},{\"label\":\"aifc\"", 0x877)      = 2167 0
3728/0x55df:  write(0x1, "Content-Length: 92\r\nContent-Type: application/vscode-jsonrpc; charset=utf8\r\n\r\n{\"jsonrpc\":\"2.0\",\"id\":80,\"result\":[{\"startLine\":3,\"endLine\":4},{\"startLine\":7,\"endLine\":8}]}\0", 0xAA)

It looks like 0x1 is getting some string output

References