mirror of
https://github.com/QB64-Phoenix-Edition/QB64pe.git
synced 2024-09-09 15:10:18 +00:00
Fairly straightfowrad, programs were randomly seg faulting on exit. This was happening due to GLUT registering a cleanup function via atexit(), which then gets called when exit() is called. The issue happens when exit() is called on a thread other than the GLUT thread, which leads to the exit() call then attempting to cleanup GLUT while the other thread is still using it, which randomly leads to seg faults. Fixing this is slightly annoying. We cannot stop the GLUT thread, as the basic GLUT API (which is used on Mac OS) simply does not offer a way to exit the glutMainLoop() call. Thus the simplest solution is to simply make sure we call exit() on the GLUT thread, which we can fairly easily due via the message queue. That being the case, a new libqb_exit() API was added, which simply regsiters the GLUT exit message and then waits for the program to end. The atexit() handler then runs on the GLUT thread and everything works out fine. In the future we probably should redo the exit logic a bit so that all the threads are actually stopped/joined to ensure the exit process is consistent, however this is good enough for now. Also, there's plenty of error states which call exit() which I did not address.
50 lines
1.7 KiB
C
50 lines
1.7 KiB
C
#ifndef INCLUDE_LIBQB_GLUT_THREAD_H
|
|
#define INCLUDE_LIBQB_GLUT_THREAD_H
|
|
|
|
// Called to potentially setup GLUT before starting the program.
|
|
void libqb_glut_presetup(int argc, char **argv);
|
|
|
|
// Starts the "main thread", including handling all the GLUT setup.
|
|
void libqb_start_main_thread(int argc, char **argv);
|
|
|
|
// Used to support _ScreenShow, which can start the GLUT thread after the
|
|
// program is started
|
|
void libqb_start_glut_thread();
|
|
|
|
// Indicates whether GLUT is currently running (and thus whether we're able to
|
|
// do any GLUT-related stuff
|
|
bool libqb_is_glut_up();
|
|
|
|
// Called at consistent intervals from a GLUT callback
|
|
void libqb_process_glut_queue();
|
|
|
|
// Called to properly exit the program. Necessary because GLUT requires a
|
|
// special care to not seg-fault when exiting the program.
|
|
void libqb_exit(int);
|
|
|
|
// These functions perform the same actions as their coresponding glut* functions.
|
|
// They tell the GLUT thread to perform the command, returning the result if applicable
|
|
void libqb_glut_set_cursor(int style);
|
|
void libqb_glut_warp_pointer(int x, int y);
|
|
int libqb_glut_get(int id);
|
|
void libqb_glut_iconify_window();
|
|
void libqb_glut_position_window(int x, int y);
|
|
void libqb_glut_show_window();
|
|
void libqb_glut_hide_window();
|
|
void libqb_glut_set_window_title(const char *title);
|
|
void libqb_glut_exit_program(int exitcode);
|
|
|
|
// Convinence macros, exists a function depending on the state of GLUT
|
|
#define NEEDS_GLUT(error_result) do { \
|
|
if (!libqb_is_glut_up()) { \
|
|
error(5); \
|
|
return error_result; \
|
|
} \
|
|
} while (0)
|
|
|
|
#define OPTIONAL_GLUT(result) do { \
|
|
if (!libqb_is_glut_up()) \
|
|
return result; \
|
|
} while (0)
|
|
|
|
#endif
|