labath wrote:

> who has the handle would be able to use them

They are, but unless they know about them, the FD is just going to sit there, 
forever.

I love to educate people about FDs, so here's a crash course. Suppose you want 
to communicate with a child process. Here's one way to do this:
```
pipe(fds);
fcntl(fds[0], F_SETFD, O_CLOEXEC);
if (fork() == 0)
  execl("program", to_string(fds[1]).c_str());
else
  close(fds[1]);
```
This works in that the other process gets one (and only one) end of the pipe 
and is made aware of its number (via the cmdline arg). The problem is you run 
the same code on two threads simultaneously. If the threads run in lockstep, 
they will first create two pipes and then fork two subprocesses. Each of those 
processes will get both pipes even though it's expecting only one.

A solution to that is to ensure the flag is cleared only inside the child 
process:
```
pipe2(fds, O_CLOEXEC);
if (fork() == 0) {
  fcntl(fds[1], F_SETFD, 0);
  execl("program", to_string(fds[1]).c_str());
} else
  close(fds[1]);
```

This way, even if both child processes end up with the extraneous pipe, the 
pipe will be automatically closed due to O_CLOEXEC. Only the one which we 
expect will have its flag cleared. This patch lets us to that (while accounting 
for all of the layers that this information needs to step through).


(Note that this still means that the FD will exist in the child process until 
the execve call. This is usually not a problem, since that's only a brief 
moment, but in some situations it can be, and it's why we have the ETXTBUSY 
workaround in the launching code (because android's ADB had this issue). 
Unfortunately, fixing this is a lot trickier. The only way I'm aware of 
involves using a "fork server" -- forking a new process at the beginning of 
main (while you're still hopefully single threaded and don't have any extra 
FDs) and then using this process to fork any new children (communicating with 
it over a domain socket, and using the socket to pass any FDs that you want to 
pass).

https://github.com/llvm/llvm-project/pull/126935
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to