LibC: implement and call __cxa_finalize() on exit()
This allows global destructors to be actually called
This commit is contained in:
parent
0b5fcb3f88
commit
7c6832cee4
|
@ -1,35 +1,37 @@
|
|||
#include <icxxabi.h>
|
||||
|
||||
#define ATEXIT_MAX_FUNCS 128
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef unsigned uarch_t;
|
||||
|
||||
struct atexit_func_entry_t
|
||||
{
|
||||
/*
|
||||
* Each member is at least 4 bytes large. Such that each entry is 12bytes.
|
||||
* 128 * 12 = 1.5KB exact.
|
||||
**/
|
||||
void (*destructor_func)(void *);
|
||||
void *obj_ptr;
|
||||
void *dso_handle;
|
||||
void (*destructor)(void*);
|
||||
void* data;
|
||||
void* dso_handle;
|
||||
};
|
||||
|
||||
atexit_func_entry_t __atexit_funcs[ATEXIT_MAX_FUNCS];
|
||||
uarch_t __atexit_func_count = 0;
|
||||
static atexit_func_entry_t __atexit_funcs[ATEXIT_MAX_FUNCS];
|
||||
static int __atexit_func_count = 0;
|
||||
|
||||
int __cxa_atexit(void (*f)(void *), void *objptr, void *dso)
|
||||
int __cxa_atexit(void (*func)(void*), void* data, void* dso_handle)
|
||||
{
|
||||
if (__atexit_func_count >= ATEXIT_MAX_FUNCS) {return -1;};
|
||||
__atexit_funcs[__atexit_func_count].destructor_func = f;
|
||||
__atexit_funcs[__atexit_func_count].obj_ptr = objptr;
|
||||
__atexit_funcs[__atexit_func_count].dso_handle = dso;
|
||||
if (__atexit_func_count >= ATEXIT_MAX_FUNCS)
|
||||
return -1;;
|
||||
__atexit_funcs[__atexit_func_count].destructor = func;
|
||||
__atexit_funcs[__atexit_func_count].data = data;
|
||||
__atexit_funcs[__atexit_func_count].dso_handle = dso_handle;
|
||||
__atexit_func_count++;
|
||||
return 0; /*I would prefer if functions returned 1 on success, but the ABI says...*/
|
||||
return 0;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
#endif
|
||||
void __cxa_finalize(void* func)
|
||||
{
|
||||
for (int i = __atexit_func_count - 1; i >= 0; i--)
|
||||
{
|
||||
if (func && func != __atexit_funcs[i].destructor)
|
||||
continue;
|
||||
if (__atexit_funcs[i].destructor == nullptr)
|
||||
continue;
|
||||
__atexit_funcs[i].destructor(__atexit_funcs[i].data);
|
||||
__atexit_funcs[i].destructor = nullptr;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
#pragma once
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
int __cxa_atexit(void (*func)(void*), void* data, void* dso_handle);
|
||||
void __cxa_finalize(void* func);
|
||||
|
||||
__END_DECLS
|
|
@ -7,6 +7,8 @@
|
|||
#include <sys/syscall.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <icxxabi.h>
|
||||
|
||||
extern "C" char** environ;
|
||||
|
||||
extern "C" void _fini();
|
||||
|
@ -21,6 +23,7 @@ void abort(void)
|
|||
void exit(int status)
|
||||
{
|
||||
fflush(nullptr);
|
||||
__cxa_finalize(nullptr);
|
||||
_fini();
|
||||
_exit(status);
|
||||
ASSERT_NOT_REACHED();
|
||||
|
|
Loading…
Reference in New Issue