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:
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user