mirror of
https://github.com/RGBCube/serenity
synced 2025-05-14 09:34:59 +00:00
LibCore+LibC: Enforce the global event loop ban in code
It's a bad idea to have a global event loop in a client application as that will cause an initialization-order fiasco in ASAN. Therefore, LibC now has a flag "s_global_initializers_ran" which is false until _entry in crt0 runs, which in turn only gets called after all the global initializers were actually executed. The EventLoop constructor checks the flag and crashes the program if it is being called as a global constructor. A note next to the VERIFY_NOT_REACHED() informs the developer of these things and how we usually instantiate event loops. The upshot of this is that global event loops will cause a crash before any undefined behavior is hit.
This commit is contained in:
parent
888faa3c9f
commit
df6b9cdb0c
3 changed files with 20 additions and 0 deletions
|
@ -15,6 +15,7 @@
|
|||
extern "C" {
|
||||
|
||||
extern size_t __stack_chk_guard;
|
||||
extern bool s_global_initializers_ran;
|
||||
|
||||
int main(int, char**, char**);
|
||||
|
||||
|
@ -41,6 +42,8 @@ int _entry(int argc, char** argv, char** env)
|
|||
__environ_is_malloced = false;
|
||||
__begin_atexit_locking();
|
||||
|
||||
s_global_initializers_ran = true;
|
||||
|
||||
_init();
|
||||
|
||||
int status = main(argc, argv, environ);
|
||||
|
|
|
@ -19,6 +19,7 @@ __thread int errno;
|
|||
char** environ;
|
||||
bool __environ_is_malloced;
|
||||
bool __stdio_is_initialized;
|
||||
bool s_global_initializers_ran;
|
||||
void* __auxiliary_vector;
|
||||
|
||||
static void __auxiliary_vector_init();
|
||||
|
|
|
@ -35,6 +35,10 @@
|
|||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef __serenity__
|
||||
extern bool s_global_initializers_ran;
|
||||
#endif
|
||||
|
||||
namespace Core {
|
||||
|
||||
class InspectorServerConnection;
|
||||
|
@ -284,6 +288,18 @@ private:
|
|||
EventLoop::EventLoop([[maybe_unused]] MakeInspectable make_inspectable)
|
||||
: m_private(make<Private>())
|
||||
{
|
||||
#ifdef __serenity__
|
||||
if (!s_global_initializers_ran) {
|
||||
// NOTE: Trying to have an event loop as a global variable will lead to initialization-order fiascos,
|
||||
// as the event loop constructor accesses and/or sets other global variables.
|
||||
// Therefore, we crash the program before ASAN catches us.
|
||||
// If you came here because of the assertion failure, please redesign your program to not have global event loops.
|
||||
// The common practice is to initialize the main event loop in the main function, and if necessary,
|
||||
// pass event loop references around or access them with EventLoop::with_main_locked() and EventLoop::current().
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!s_event_loop_stack) {
|
||||
s_event_loop_stack = new Vector<EventLoop&>;
|
||||
s_timers = new HashMap<int, NonnullOwnPtr<EventLoopTimer>>;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue