Commit 170e07c
committed
Close inherited file descriptors in forked child processes
ScriptController::StartProcess() forks a child to run unrar/7z or an
extension/post-processing script, but only ever closes the pipe fds
it created itself before calling execvp(). Any other file descriptor
the main process happens to have open at that exact moment is
inherited unchanged into the child (execvp does not close fds unless
they are marked close-on-exec).
In practice this means: if the main process has a file briefly open
for one queue item (e.g. mid-rename during Move) at the instant it
forks a child for a completely unrelated item (another unpack, or an
extension script), that unrelated child inherits the handle. The
original file then appears "busy" to the OS/filesystem for as long as
that unrelated child keeps running, and the Move fails with EBUSY
("Resource busy" on NFS mounts, surfaced as a "silly rename" .nfsXXXX
file).
Fix: compute the process's open-fd ceiling via sysconf(_SC_OPEN_MAX)
before fork() (sysconf is not async-signal-safe, so it can't be called
in the child), then in the child, after the stdin/stdout/stderr pipe
fds are wired up, close every other fd before execvp().1 parent 6719a67 commit 170e07c
1 file changed
Lines changed: 21 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
579 | 579 | | |
580 | 580 | | |
581 | 581 | | |
| 582 | + | |
| 583 | + | |
| 584 | + | |
| 585 | + | |
| 586 | + | |
| 587 | + | |
| 588 | + | |
| 589 | + | |
| 590 | + | |
582 | 591 | | |
583 | 592 | | |
584 | 593 | | |
| |||
619 | 628 | | |
620 | 629 | | |
621 | 630 | | |
| 631 | + | |
| 632 | + | |
| 633 | + | |
| 634 | + | |
| 635 | + | |
| 636 | + | |
| 637 | + | |
| 638 | + | |
| 639 | + | |
| 640 | + | |
| 641 | + | |
| 642 | + | |
622 | 643 | | |
623 | 644 | | |
624 | 645 | | |
| |||
0 commit comments