From 744616c074400f51dd6ddd5c88e7a8e676505f1b Mon Sep 17 00:00:00 2001 From: Augustin Cavalier Date: Thu, 9 Apr 2026 14:07:18 -0400 Subject: [PATCH] libroot_build: Rework errno assignment. With the old code, if the currentErrno hadn't changed, but was in fact re-assigned more recently than the local errno was, then we would wind up incorrectly return the local value instead of the system value. This was the cause of the build mimeset not working properly when run in recursive mode on Haiku. So, instead, create a wrapper struct to make assignment of the local errno always pass through to the system one, so they never get out of sync in the first place. --- headers/build/os/support/Errors.h | 33 +++++++++++++++---- src/build/libroot/errors.cpp | 54 +++++++++++++++++-------------- 2 files changed, 56 insertions(+), 31 deletions(-) diff --git a/headers/build/os/support/Errors.h b/headers/build/os/support/Errors.h index a07d8c1386..04d36b41ad 100644 --- a/headers/build/os/support/Errors.h +++ b/headers/build/os/support/Errors.h @@ -494,23 +494,44 @@ #define ENOEXEC HAIKU_ENOEXEC #define EPIPE HAIKU_EPIPE #define ENOATTR HAIKU_ENOATTR - - #undef errno - #define errno (*_haiku_build_errno()) #elif defined(HAIKU_HOST_PLATFORM_HAIKU) -# include <../os/support/Errors.h> +# include_next #endif // ! BUILDING_HAIKU_ERROR_MAPPER #ifdef __cplusplus extern "C" { #endif -extern int *_haiku_build_errno(); +extern const int _haiku_build_errno(); +extern void _haiku_build_set_errno(int error); extern int _haiku_to_host_error(int error); #ifdef __cplusplus -} +} // extern "C" + +struct BuildErrnoWrapper { + int operator=(int value) + { + _haiku_build_set_errno(value); + return value; + } + operator int() + { + return _haiku_build_errno(); + } +}; #endif +/* build-specific code */ +#ifndef BUILDING_HAIKU_ERROR_MAPPER +#undef errno +#ifndef __cplusplus +#define errno (_haiku_build_errno()) +#else +extern BuildErrnoWrapper build_errno; +#define errno build_errno +#endif +#endif // ! BUILDING_HAIKU_ERROR_MAPPER + #endif /* _BUILD_ERRORS_H */ diff --git a/src/build/libroot/errors.cpp b/src/build/libroot/errors.cpp index bd8aa7e299..245e4c46fb 100644 --- a/src/build/libroot/errors.cpp +++ b/src/build/libroot/errors.cpp @@ -183,34 +183,38 @@ _haiku_build_strerror(int errnum) return strerror(to_host_error(errnum)); } -// _haiku_build_errno -int * -_haiku_build_errno() -{ - static int previousErrno = 0; - static int localErrno = 0; - static int previousLocalErrno = 0; - - // If the localErrno has been changed and the real errno has not changed - // in the meantime, we update errno itself, so that the local update will - // be reflected. If errno has changed we always update localErrno. - int currentErrno = errno; - if (currentErrno == previousErrno) { - if (localErrno != previousLocalErrno) { - errno = previousErrno = to_host_error(localErrno); - previousLocalErrno = localErrno; - } - } else { - previousErrno = currentErrno; - previousLocalErrno = localErrno = to_haiku_error(errno); - } - - return &localErrno; -} - // _haiku_to_host_error int _haiku_to_host_error(int error) { return to_host_error(error); } + + +// #pragma mark - errno handling + + +BuildErrnoWrapper build_errno; +static int sPreviousErrno = 0; +static int sLocalErrno = 0; + + +const int +_haiku_build_errno() +{ + int currentErrno = errno; + if (currentErrno != sPreviousErrno) { + sPreviousErrno = currentErrno; + sLocalErrno = to_haiku_error(currentErrno); + } + + return sLocalErrno; +} + + +void +_haiku_build_set_errno(int error) +{ + sLocalErrno = error; + errno = sPreviousErrno = to_host_error(error); +}