From 2fac0f0b395279eac63f34aa2d7a4ba988e18c50 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Sun, 14 Apr 2019 16:08:29 -0700 Subject: [PATCH] Correctly lock around umask umask can only be set, never just queried. Thus we need to lock around calls to it. Also guess the value; if we guess right we don't need to reset it. --- src/env.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/env.cpp b/src/env.cpp index d40f98c75..a88a28c87 100644 --- a/src/env.cpp +++ b/src/env.cpp @@ -112,9 +112,14 @@ static maybe_t get_electric(const wcstring &key, const environment_t return env_var_t(L"status", to_string(proc_get_last_status())); } else if (key == L"umask") { // note umask() is an absurd API: you call it to set the value and it returns the old value. - // Thus we have to call it twice, to reset the value. TODO: lock! - mode_t res = umask(0); - umask(res); + // Thus we have to call it twice, to reset the value. + // We need to lock since otherwise this races. + // Guess what the umask is; if we guess right we don't need to reset it. + static std::mutex umask_lock; + scoped_lock locker(umask_lock); + int guess = 022; + mode_t res = umask(guess); + if (res != guess) umask(res); return env_var_t(L"umask", format_string(L"0%0.3o", res)); } // We should never get here unless the electric var list is out of sync with the above code.