3 ms·
Hot take: if a crash can be made to disappear just by adding a mutex inside setenv(), this means code reading the environment is racing with code writing to it,
by tsukikage 3y ago
Hot take: if a crash can be made to disappear just by adding a mutex inside setenv(), this means code reading the environment is racing with code writing to it, and in this situation adding a mutex inside setenv() will generally make things worse instead of better: it may hide the immediate symptom, but the underlying race between reading and writing to the environment remains, your program will behave differently each run depending on who wins the race (with potentially catastrophic results depending on what the writes are doing), and the cause will be much harder to debug from cold due to the lack of a smoking gun pointing at environment manipulation.
The multithreaded program needs to be restructured so that the parts that communicate via the environment are properly serialised with respect to each other, just as would be needed for any other communication via global state and/or access to a shared resource.
This has to happen at a higher level than the individual getenv/setenv calls: entire blocks of logic containing the calls need to be made atomic (or otherwise refactored; perhaps you could do all the environment writes before spawning any threads) so that no other thread can blow away the environment contents in between the code that sets it up for some purpose and the code that implements that purpose; and once this is properly done, the individual calls themselves do not need further protection.
- hddqsb 3y agoSure, some applications might require custom higher-level synchronisation, but it's still important for getenv/setenv to be thread-safe (i.e. not crash): - The race might be irrelevant (e.g. simultaneous calls that access different variables are fine). - The application author might not have complete control over all calls to getenv/setenv (e.g. if using a third-party library).