add utils for passing file descriptor between processes - #4019
add utils for passing file descriptor between processes#4019echoechoin wants to merge 26 commits into
Conversation
0f6a823 to
8ee8195
Compare
| } | ||
|
|
||
| /* get fd_to_send by open /proc/PID/fd/FD */ | ||
| fd_to_send = open(proc_path, O_RDWR); |
There was a problem hiding this comment.
open(2) works for an fd opening a regular file.
For fds opening peculiar objects like sockets, we can use pidfd_getfd as a fallback.
There was a problem hiding this comment.
How about using pidfd_getfd at first, then fall back to open if errno == ENOSYS || errno == EPERM.
There was a problem hiding this comment.
The semantics of calling open(/proc/$pid/fd/$fd) and of calling pidfd_getfd($fd) differ.
open makes a new open file object in the kernel.
pidfd_getfd doesn't. pidfd_getfd makes a new reference to the open file.
If a receiver process calls lseek on a received file descriptor, it affects on the open file behind the fd.
open(2)
[target process]<fd> ------ [file object] --- [dentry] --- [inode]
/
[receiver process]<fd> -----[file object] --/
pidfd_getfd(2)
[target process]<fd> ------ [file object] --- [dentry] --- [inode]
/
[receiver process]<fd> ----/
I would like to withdraw my comment.
I think users expect the behavior of open(2). So, using the open(2) method is better as the default method.
What about activating the pidfd_getfd(2) method only if --pidfd-getfd option is given?
There was a problem hiding this comment.
Now I believe it is better to activate the pidfd_getfd(2) method only if --pidfd-getfd option is given. No fallback.
|
It seems you need to add bash-completion files for your new commands. |
| opt_pid = strtopid_or_err(optarg, _("invalid pid")); | ||
| if (opt_pid < 1) | ||
| errx(EXIT_FAILURE, _("pid must be positive")); |
There was a problem hiding this comment.
You can also use this internal lib function. It would make way for a potential PID:inode support which could be interesting for fd{recv,send}, since it'll help avoid sending/receiving a fd from/to a wrong process (in cases where that is important of course).
| opt_pid = strtopid_or_err(optarg, _("invalid pid")); | |
| if (opt_pid < 1) | |
| errx(EXIT_FAILURE, _("pid must be positive")); | |
| opt_pid = ul_parse_pid_str_or_err(optarg, &opt_pid, NULL); |
There was a problem hiding this comment.
For some context in regards to PID:inode: #3953 (comment)
|
What about extending fdrecv to receive multiple fds? |
How about this: # Send multiple fds:
fdsend --block --fd 0,1,2 -b pipe_test
# Receive multiple fds:
fdrecv --fd 0,1,2 pipe_test --run cat # 0 <-> 0, 1 <-> 1, 2 <-> 2 (full mapping)
fdrecv --fd 0,1 pipe_test --run cat # 0 <-> 0, 1 <-> 1 (2 is ignored)
fdrecv --fd 0 pipe_test --run cat # 0 <-> 0 (1 and 2 are ignored)Also ensure that # Send multiple fds:
fdsend --block --fd 0,1,2 -b pipe_test
# Receive only first fd via --stdin, --stdout, or --stderr:
fdrecv --stdin pipe_test --run cat # 0 <-> stdin, ignore other fds. |
f7cc796 to
1931ac9
Compare
4f0da87 to
215f250
Compare
|
What about supporting an abstract Unix socket (https://man7.org/linux/man-pages/man7/unix.7.html)? |
How about add a new command option for abstract unix socket? fdsend --abstract --fd 1 sockspec
fdrecv --abstract --fd 1 sockspec run cator add an |
|
Adding Rationals:
For abstract sockets, we cannot use inotify to detect the appearance of a listening socket. So the usability of these commands with
|
|
In |
|
I don't have any other idea than the polling approach. |
| * Receiver: socket/bind/listen/accept, recvmsg with SCM_RIGHTS. | ||
| * On success sets *out_fd to the received fd and returns 0. | ||
| */ | ||
| static int fdrecv_accept_and_recv_fd(const char *sockpath, int *out_fd, int abstract) |
Check warning
Code scanning / CodeQL
Poorly documented large function Warning
7e2f180 to
b97707e
Compare
b97707e to
afd3921
Compare
f865d19 to
993f975
Compare
| FILE *out = stdout; | ||
|
|
||
| fputs(USAGE_HEADER, out); | ||
| fprintf(out, _(" %s [options] SOCKSPEC --run command args...\n"), program_invocation_short_name); |
There was a problem hiding this comment.
I find that --run is a bit unnecessary. Since SOCKSPEC can not be specified an arbitrary amount of time, we can simply design the CLI like this:
fdrecv [options] SOCKSPEC COMMAND
COMMAND will have an arbitrary amount of arguments, which is fine as these will be the remaining elements of argv and we'll just pass them to execvp(2).
What do you think ?
There was a problem hiding this comment.
If we extend fdrecv to accept fds from multiple sockets, the fdcecv command line can become complicated. In these cases, the --run option helps people understand the command line.
If the action that fdrecv takes after receiving all fds is only "run", we can choose -- (or -) instead of --run.
|
It would be nice if fdrecv could receive multiple fds from different sockets at once. terminal A terminal B terminal C trminal recv: |
This commit implements the fdsend and fdrecv utilities as proposed in Discussion util-linux#3683. It adds: - fdsend: send a file descriptor to a Unix domain socket (path-based). Supports blocking wait for receiver, optional pid/fd resolution, and pidfd_getfd(2) where available. - fdrecv: receive a file descriptor from a Unix domain socket and optionally exec a program with the received fd. Signed-off-by: WanBingjiang <wanbingjiang@webray.com.cn>
Signed-off-by: WanBingjiang <wanbingjiang@webray.com.cn>
Signed-off-by: WanBingjiang <wanbingjiang@webray.com.cn>
Signed-off-by: WanBingjiang <wanbingjiang@webray.com.cn>
Signed-off-by: WanBingjiang <wanbingjiang@webray.com.cn>
Allow using pidfd_getfd(2) instead of open(/proc/PID/fd/FD) to obtain the file descriptor from the process. Signed-off-by: WanBingjiang <wanbingjiang@webray.com.cn>
Signed-off-by: WanBingjiang <wanbingjiang@webray.com.cn>
Add the shared fdsend-common.h to fdsend_SOURCES and fdrecv_SOURCES so make dist packs the header. Signed-off-by: WanBingjiang <wanbingjiang@webray.com.cn>
Signed-off-by: WanBingjiang <wanbingjiang@webray.com.cn>
Signed-off-by: WanBingjiang <wanbingjiang@webray.com.cn>
Signed-off-by: WanBingjiang <wanbingjiang@webray.com.cn>
Signed-off-by: WanBingjiang <wanbingjiang@webray.com.cn>
…usage message for clarity Signed-off-by: WanBingjiang <wanbingjiang@webray.com.cn>
- Support multiple -f N SOCKSPEC (and -i/-o/-e SOCKSPEC) before --run CMD. - Add `relocate_conflicting_fds` to avoid target FD and received FD conflicts. - Add fdrecv doc update and tests. Signed-off-by: WanBingjiang <wanbingjiang@webray.com.cn>
Signed-off-by: WanBingjiang <wanbingjiang@webray.com.cn>
Replace manual string copies and path splitting in sockpath_from_spec() and fdsend_wait_for_socket() with xstrncpy(), xasprintf(), stripoff_last_component() and ul_path_get_abspath(). Signed-off-by: WanBingjiang <wanbingjiang@webray.com.cn>
Signed-off-by: WanBingjiang <wanbingjiang@webray.com.cn>
Signed-off-by: WanBingjiang <wanbingjiang@webray.com.cn>
Signed-off-by: WanBingjiang <wanbingjiang@webray.com.cn>
Signed-off-by: WanBingjiang <wanbingjiang@webray.com.cn>
Signed-off-by: WanBingjiang <wanbingjiang@webray.com.cn>
Signed-off-by: WanBingjiang <wanbingjiang@webray.com.cn>
The option name --pidfd-getfd leaks an implementation detail without describing the semantic difference from the default open(/proc/PID/fd/FD) approach. Rename to --dup (-d) to convey that the fd is duplicated (shared offset and status flags) rather than opened as an independent copy. Also expand the man page to explain the difference between --dup and the default behavior. Signed-off-by: WanBingjiang <wanbingjiang@webray.com.cn>
Accept --pid 12345:67890 syntax to validate the pidfd inode, preventing PID reuse races when using --dup. Signed-off-by: WanBingjiang <wanbingjiang@webray.com.cn>
Default remains O_RDWR. Accepts --mode r (O_RDONLY), r+ (O_RDWR) or w (O_WRONLY). Mutually exclusive with --dup. Signed-off-by: WanBingjiang <wanbingjiang@webray.com.cn>
f86408f to
954b681
Compare
SIGINT/SIGTERM/SIGHUP now break out of the blocking connect-retry loop and the inotify socket-wait loop gracefully with EINTR instead of requiring the process to be killed. Merge the separate fdrecv and fdsend signal handler sets into one shared handler. Signed-off-by: WanBingjiang <wanbingjiang@webray.com.cn>
954b681 to
5541fea
Compare
Based on the outcomes of Discussion #3683, I have developed this demo, with the relevant operation example as follows: