Repository navigation
uucore: add mode::with_umask - #15121
abendrothj wants to merge 3 commits into
Conversation
Merging this PR will degrade performance by 33.07%
|
| Mode | Benchmark | BASE |
HEAD |
Efficiency | |
|---|---|---|---|---|---|
| ❌ | Simulation | factor_three_39_bit_primes |
300.2 ms | 817 ms | -63.25% |
| ❌ | Simulation | factor_five_38_bit_primes |
1.6 s | 1.9 s | -13.99% |
| ❌ | Simulation | factor_thirteen_39_bit_primes |
8.9 s | 9.4 s | -5.14% |
Tip
Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.
Comparing abendrothj:uucore-with-umask (b434a5c) with main (98f90f2)2
Footnotes
-
70 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports. ↩
-
No successful run was found on
main(9c8b347) during the generation of this report, so 98f90f2 was used instead as the comparison base. There might be some changes unrelated to this pull request in this report. ↩
|
|
||
| // `rustix::fs::RawMode` is u16 on some targets and u32 on others. | ||
| #[cfg(unix)] | ||
| fn mode_from_umask(mask: u32) -> rustix::fs::Mode { |
There was a problem hiding this comment.
used once, could be inlined in UmaskGuard::set, no?
| } | ||
|
|
||
| #[cfg(unix)] | ||
| struct UmaskGuard(rustix::fs::Mode); |
There was a problem hiding this comment.
mkdir.rs and sort/tmp_dir.rs already have their own UmaskGuard, could you please switch them to this in the same PR?
for now it has no caller
There was a problem hiding this comment.
done, in two commits: mkdir and the sort test use it now. mkdir's shaped mask is a plain u32, so it drops rustix. its umask tests (15 of them) check the resulting modes; nothing tests two threads on the umask.
| /// | ||
| /// The previous umask is restored when the operation returns or unwinds. | ||
| /// Calls through this module are serialized because the umask is process-wide. | ||
| /// The lock is not reentrant: calling [`get_umask`] or `with_umask` from |
There was a problem hiding this comment.
a deadlock on a nested get_umask is easy to hit (cp/mkdir call it everywhere), could we make it reentrant instead?
There was a problem hiding this comment.
done: the thread holding the lock skips it, and get_umask there returns the mask in effect. test_with_umask_nests hung before and passes now. other threads still wait, so the closure must not wait on one of them.
| /// Calls through this module are serialized because the umask is process-wide. | ||
| /// The lock is not reentrant: calling [`get_umask`] or `with_umask` from | ||
| /// `operation` deadlocks. | ||
| #[cfg(unix)] |
There was a problem hiding this comment.
why only unix? get_umask takes the lock on windows too
There was a problem hiding this comment.
nothing sets the umask on windows (mkdir's guard was unix-only too), so I dropped the lock there instead.
6c97e71 to
28f64a5
Compare
|
The expand numbers aren't from this PR: expand doesn't enable uucore's |
Utilities that create files or directories at an exact mode, whatever the caller's umask, change the process umask around the call. Done by hand, overlapping calls can restore each other's mask and leave the process at the wrong value, and an unwind between the set and the restore leaks the temporary mask. with_umask runs an operation with a temporary umask, holds a mutex shared with get_umask, and restores the previous mask on return or unwind. Calls nest: the thread that holds the mutex skips it, and get_umask there returns the mask in effect. Only Unix sets the umask this way, so Windows' get_umask takes no lock.
Replace mkdir's own umask guard with the shared helper, so its change is serialized with get_umask and other callers. The shaped umask is computed as a plain mask, which drops mkdir's rustix dependency.
The test set and restored the umask with its own guard, outside the lock that get_umask and with_umask share.
28f64a5 to
b434a5c
Compare
install, mkdir, mkfifo and mknod need to change the process-wide umask around a few syscalls. Done by hand, two overlapping changes can restore each other's mask, and a panic between set and restore leaks the temporary mask.
uucore::mode::with_umaskruns a closure with the given umask while holding the same mutex asget_umask, and restores the previous mask before releasing it, also on unwind. Calls nest: on the thread holding the mutex,with_umaskandget_umaskskip it, andget_umaskreturns the mask in effect. Windows'get_umasktakes no lock, since nothing sets the umask there.mkdir and the sort tmp_dir test switch to it from their own guards; mkdir no longer needs rustix. Tests check the mask is set inside and restored after, also when nested.
No user-visible change; also used by #12715 and #14768.
Part of #12714 and #14994