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.
This commit is contained in:
Augustin Cavalier
2026-04-09 14:09:52 -04:00
parent 95c8251d75
commit 744616c074
2 changed files with 56 additions and 31 deletions
+27 -6
View File
@@ -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 <Errors.h>
#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 */
+29 -25
View File
@@ -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);
}