main: SDL_AppQuit() now reports the result value.

Fixes #10994.
This commit is contained in:
Ryan C. Gordon 2024-09-29 22:17:11 -04:00
parent 6a7f8b74f1
commit 1787d6ca5c
37 changed files with 48 additions and 42 deletions

View file

@ -190,7 +190,7 @@ to SDL_EVENT_QUIT, etc.
Finally: Finally:
```c ```c
void SDL_AppQuit(void *appstate); void SDL_AppQuit(void *appstate, SDL_AppResult result);
``` ```
This is called once before terminating the app--assuming the app isn't being This is called once before terminating the app--assuming the app isn't being
@ -201,3 +201,6 @@ from main(), so atexit handles will run, if your platform supports that.
If you set `*appstate` during SDL_AppInit, this is where you should free that If you set `*appstate` during SDL_AppInit, this is where you should free that
data, as this pointer will not be provided to your app again. data, as this pointer will not be provided to your app again.
The SDL_AppResult value that terminated the app is provided here, in case
it's useful to know if this was a successful or failing run of the app.

View file

@ -92,7 +92,7 @@ SDL_AppResult SDL_AppIterate(void *appstate)
} }
/* This function runs once at shutdown. */ /* This function runs once at shutdown. */
void SDL_AppQuit(void *appstate) void SDL_AppQuit(void *appstate, SDL_AppResult result)
{ {
/* SDL will clean up the window/renderer for us. */ /* SDL will clean up the window/renderer for us. */
} }

View file

@ -104,7 +104,7 @@ SDL_AppResult SDL_AppIterate(void *appstate)
} }
/* This function runs once at shutdown. */ /* This function runs once at shutdown. */
void SDL_AppQuit(void *appstate) void SDL_AppQuit(void *appstate, SDL_AppResult result)
{ {
/* SDL will clean up the window/renderer for us. */ /* SDL will clean up the window/renderer for us. */
} }

View file

@ -93,7 +93,7 @@ SDL_AppResult SDL_AppIterate(void *appstate)
} }
/* This function runs once at shutdown. */ /* This function runs once at shutdown. */
void SDL_AppQuit(void *appstate) void SDL_AppQuit(void *appstate, SDL_AppResult result)
{ {
SDL_free(wav_data); /* strictly speaking, this isn't necessary because the process is ending, but it's good policy. */ SDL_free(wav_data); /* strictly speaking, this isn't necessary because the process is ending, but it's good policy. */
/* SDL will clean up the window/renderer for us. */ /* SDL will clean up the window/renderer for us. */

View file

@ -103,7 +103,7 @@ SDL_AppResult SDL_AppIterate(void *appstate)
} }
/* This function runs once at shutdown. */ /* This function runs once at shutdown. */
void SDL_AppQuit(void *appstate) void SDL_AppQuit(void *appstate, SDL_AppResult result)
{ {
SDL_CloseCamera(camera); SDL_CloseCamera(camera);
SDL_DestroyTexture(texture); SDL_DestroyTexture(texture);

View file

@ -320,7 +320,7 @@ SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event)
return SDL_APP_CONTINUE; return SDL_APP_CONTINUE;
} }
void SDL_AppQuit(void *appstate) void SDL_AppQuit(void *appstate, SDL_AppResult result)
{ {
if (appstate != NULL) { if (appstate != NULL) {
AppState *as = (AppState *)appstate; AppState *as = (AppState *)appstate;

View file

@ -96,7 +96,7 @@ SDL_AppResult SDL_AppIterate(void *appstate)
} }
/* This function runs once at shutdown. */ /* This function runs once at shutdown. */
void SDL_AppQuit(void *appstate) void SDL_AppQuit(void *appstate, SDL_AppResult result)
{ {
SDL_DestroyTexture(render_target); SDL_DestroyTexture(render_target);
/* SDL will clean up the window/renderer for us. */ /* SDL will clean up the window/renderer for us. */

View file

@ -59,7 +59,7 @@ SDL_AppResult SDL_AppIterate(void *appstate)
} }
/* This function runs once at shutdown. */ /* This function runs once at shutdown. */
void SDL_AppQuit(void *appstate) void SDL_AppQuit(void *appstate, SDL_AppResult result)
{ {
/* SDL will clean up the window/renderer for us. */ /* SDL will clean up the window/renderer for us. */
} }

View file

@ -86,7 +86,7 @@ SDL_AppResult SDL_AppIterate(void *appstate)
} }
/* This function runs once at shutdown. */ /* This function runs once at shutdown. */
void SDL_AppQuit(void *appstate) void SDL_AppQuit(void *appstate, SDL_AppResult result)
{ {
/* SDL will clean up the window/renderer for us. */ /* SDL will clean up the window/renderer for us. */
} }

View file

@ -84,7 +84,7 @@ SDL_AppResult SDL_AppIterate(void *appstate)
} }
/* This function runs once at shutdown. */ /* This function runs once at shutdown. */
void SDL_AppQuit(void *appstate) void SDL_AppQuit(void *appstate, SDL_AppResult result)
{ {
/* SDL will clean up the window/renderer for us. */ /* SDL will clean up the window/renderer for us. */
} }

View file

@ -109,7 +109,7 @@ SDL_AppResult SDL_AppIterate(void *appstate)
} }
/* This function runs once at shutdown. */ /* This function runs once at shutdown. */
void SDL_AppQuit(void *appstate) void SDL_AppQuit(void *appstate, SDL_AppResult result)
{ {
/* SDL will clean up the window/renderer for us. */ /* SDL will clean up the window/renderer for us. */
} }

View file

@ -103,7 +103,7 @@ SDL_AppResult SDL_AppIterate(void *appstate)
} }
/* This function runs once at shutdown. */ /* This function runs once at shutdown. */
void SDL_AppQuit(void *appstate) void SDL_AppQuit(void *appstate, SDL_AppResult result)
{ {
/* SDL will clean up the window/renderer for us. */ /* SDL will clean up the window/renderer for us. */
} }

View file

@ -117,7 +117,7 @@ SDL_AppResult SDL_AppIterate(void *appstate)
} }
/* This function runs once at shutdown. */ /* This function runs once at shutdown. */
void SDL_AppQuit(void *appstate) void SDL_AppQuit(void *appstate, SDL_AppResult result)
{ {
SDL_DestroyTexture(texture); SDL_DestroyTexture(texture);
/* SDL will clean up the window/renderer for us. */ /* SDL will clean up the window/renderer for us. */

View file

@ -99,7 +99,7 @@ SDL_AppResult SDL_AppIterate(void *appstate)
} }
/* This function runs once at shutdown. */ /* This function runs once at shutdown. */
void SDL_AppQuit(void *appstate) void SDL_AppQuit(void *appstate, SDL_AppResult result)
{ {
SDL_DestroyTexture(texture); SDL_DestroyTexture(texture);
/* SDL will clean up the window/renderer for us. */ /* SDL will clean up the window/renderer for us. */

View file

@ -103,7 +103,7 @@ SDL_AppResult SDL_AppIterate(void *appstate)
} }
/* This function runs once at shutdown. */ /* This function runs once at shutdown. */
void SDL_AppQuit(void *appstate) void SDL_AppQuit(void *appstate, SDL_AppResult result)
{ {
SDL_DestroyTexture(texture); SDL_DestroyTexture(texture);
/* SDL will clean up the window/renderer for us. */ /* SDL will clean up the window/renderer for us. */

View file

@ -100,7 +100,7 @@ SDL_AppResult SDL_AppIterate(void *appstate)
} }
/* This function runs once at shutdown. */ /* This function runs once at shutdown. */
void SDL_AppQuit(void *appstate) void SDL_AppQuit(void *appstate, SDL_AppResult result)
{ {
SDL_DestroyTexture(texture); SDL_DestroyTexture(texture);
/* SDL will clean up the window/renderer for us. */ /* SDL will clean up the window/renderer for us. */

View file

@ -156,7 +156,7 @@ SDL_AppResult SDL_AppIterate(void *appstate)
} }
/* This function runs once at shutdown. */ /* This function runs once at shutdown. */
void SDL_AppQuit(void *appstate) void SDL_AppQuit(void *appstate, SDL_AppResult result)
{ {
SDL_DestroyTexture(texture); SDL_DestroyTexture(texture);
/* SDL will clean up the window/renderer for us. */ /* SDL will clean up the window/renderer for us. */

View file

@ -124,7 +124,7 @@ SDL_AppResult SDL_AppIterate(void *appstate)
} }
/* This function runs once at shutdown. */ /* This function runs once at shutdown. */
void SDL_AppQuit(void *appstate) void SDL_AppQuit(void *appstate, SDL_AppResult result)
{ {
SDL_DestroyTexture(texture); SDL_DestroyTexture(texture);
/* SDL will clean up the window/renderer for us. */ /* SDL will clean up the window/renderer for us. */

View file

@ -126,7 +126,7 @@ SDL_AppResult SDL_AppIterate(void *appstate)
} }
/* This function runs once at shutdown. */ /* This function runs once at shutdown. */
void SDL_AppQuit(void *appstate) void SDL_AppQuit(void *appstate, SDL_AppResult result)
{ {
SDL_DestroyTexture(texture); SDL_DestroyTexture(texture);
/* SDL will clean up the window/renderer for us. */ /* SDL will clean up the window/renderer for us. */

View file

@ -127,7 +127,7 @@ SDL_AppResult SDL_AppIterate(void *appstate)
} }
/* This function runs once at shutdown. */ /* This function runs once at shutdown. */
void SDL_AppQuit(void *appstate) void SDL_AppQuit(void *appstate, SDL_AppResult result)
{ {
SDL_DestroyTexture(texture); SDL_DestroyTexture(texture);
/* SDL will clean up the window/renderer for us. */ /* SDL will clean up the window/renderer for us. */

View file

@ -167,7 +167,7 @@ SDL_AppResult SDL_AppIterate(void *appstate)
} }
/* This function runs once at shutdown. */ /* This function runs once at shutdown. */
void SDL_AppQuit(void *appstate) void SDL_AppQuit(void *appstate, SDL_AppResult result)
{ {
SDL_DestroyTexture(converted_texture); SDL_DestroyTexture(converted_texture);
SDL_DestroyTexture(texture); SDL_DestroyTexture(texture);

View file

@ -44,7 +44,7 @@ SDL_AppResult SDL_AppIterate(void *appstate)
} }
/* This function runs once at shutdown. */ /* This function runs once at shutdown. */
void SDL_AppQuit(void *appstate) void SDL_AppQuit(void *appstate, SDL_AppResult result)
{ {
/* SDL will clean up the window/renderer for us. */ /* SDL will clean up the window/renderer for us. */
} }

View file

@ -96,7 +96,7 @@ typedef enum SDL_AppResult
typedef SDL_AppResult (SDLCALL *SDL_AppInit_func)(void **appstate, int argc, char *argv[]); typedef SDL_AppResult (SDLCALL *SDL_AppInit_func)(void **appstate, int argc, char *argv[]);
typedef SDL_AppResult (SDLCALL *SDL_AppIterate_func)(void *appstate); typedef SDL_AppResult (SDLCALL *SDL_AppIterate_func)(void *appstate);
typedef SDL_AppResult (SDLCALL *SDL_AppEvent_func)(void *appstate, SDL_Event *event); typedef SDL_AppResult (SDLCALL *SDL_AppEvent_func)(void *appstate, SDL_Event *event);
typedef void (SDLCALL *SDL_AppQuit_func)(void *appstate); typedef void (SDLCALL *SDL_AppQuit_func)(void *appstate, SDL_AppResult result);
/** /**
* Initialize the SDL library. * Initialize the SDL library.

View file

@ -372,6 +372,7 @@ extern SDLMAIN_DECLSPEC SDL_AppResult SDLCALL SDL_AppEvent(void *appstate, SDL_E
* resources to it should be cleaned up here. * resources to it should be cleaned up here.
* *
* \param appstate an optional pointer, provided by the app in SDL_AppInit. * \param appstate an optional pointer, provided by the app in SDL_AppInit.
* \param result the result code that terminated the app (success or failure).
* *
* \threadsafety This function is not thread safe. * \threadsafety This function is not thread safe.
* *
@ -379,7 +380,7 @@ extern SDLMAIN_DECLSPEC SDL_AppResult SDLCALL SDL_AppEvent(void *appstate, SDL_E
* *
* \sa SDL_AppInit * \sa SDL_AppInit
*/ */
extern SDLMAIN_DECLSPEC void SDLCALL SDL_AppQuit(void *appstate); extern SDLMAIN_DECLSPEC void SDLCALL SDL_AppQuit(void *appstate, SDL_AppResult result);
#endif /* SDL_MAIN_USE_CALLBACKS */ #endif /* SDL_MAIN_USE_CALLBACKS */

View file

@ -130,10 +130,10 @@ SDL_AppResult SDL_IterateMainCallbacks(bool pump_events)
return rc; return rc;
} }
void SDL_QuitMainCallbacks(void) void SDL_QuitMainCallbacks(SDL_AppResult result)
{ {
SDL_RemoveEventWatch(SDL_MainCallbackEventWatcher, NULL); SDL_RemoveEventWatch(SDL_MainCallbackEventWatcher, NULL);
SDL_main_quit_callback(SDL_main_appstate); SDL_main_quit_callback(SDL_main_appstate, result);
SDL_main_appstate = NULL; // just in case. SDL_main_appstate = NULL; // just in case.
// for symmetry, you should explicitly Quit what you Init, but we might come through here uninitialized and SDL_Quit() will clear everything anyhow. // for symmetry, you should explicitly Quit what you Init, but we might come through here uninitialized and SDL_Quit() will clear everything anyhow.

View file

@ -25,7 +25,7 @@
bool SDL_HasMainCallbacks(void); bool SDL_HasMainCallbacks(void);
SDL_AppResult SDL_InitMainCallbacks(int argc, char *argv[], SDL_AppInit_func appinit, SDL_AppIterate_func _appiter, SDL_AppEvent_func _appevent, SDL_AppQuit_func _appquit); SDL_AppResult SDL_InitMainCallbacks(int argc, char *argv[], SDL_AppInit_func appinit, SDL_AppIterate_func _appiter, SDL_AppEvent_func _appevent, SDL_AppQuit_func _appquit);
SDL_AppResult SDL_IterateMainCallbacks(bool pump_events); SDL_AppResult SDL_IterateMainCallbacks(bool pump_events);
void SDL_QuitMainCallbacks(void); void SDL_QuitMainCallbacks(SDL_AppResult result);
#endif // SDL_main_callbacks_h_ #endif // SDL_main_callbacks_h_

View file

@ -28,7 +28,7 @@ static void EmscriptenInternalMainloop(void)
{ {
const SDL_AppResult rc = SDL_IterateMainCallbacks(true); const SDL_AppResult rc = SDL_IterateMainCallbacks(true);
if (rc != SDL_APP_CONTINUE) { if (rc != SDL_APP_CONTINUE) {
SDL_QuitMainCallbacks(); SDL_QuitMainCallbacks(rc);
emscripten_cancel_main_loop(); // kill" the mainloop, so it stops calling back into it. emscripten_cancel_main_loop(); // kill" the mainloop, so it stops calling back into it.
exit((rc == SDL_APP_FAILURE) ? 1 : 0); // hopefully this takes down everything else, too. exit((rc == SDL_APP_FAILURE) ? 1 : 0); // hopefully this takes down everything else, too.
} }
@ -40,7 +40,7 @@ int SDL_EnterAppMainCallbacks(int argc, char* argv[], SDL_AppInit_func appinit,
if (rc == SDL_APP_CONTINUE) { if (rc == SDL_APP_CONTINUE) {
emscripten_set_main_loop(EmscriptenInternalMainloop, 0, 0); // run at refresh rate, don't throw an exception since we do an orderly return. emscripten_set_main_loop(EmscriptenInternalMainloop, 0, 0); // run at refresh rate, don't throw an exception since we do an orderly return.
} else { } else {
SDL_QuitMainCallbacks(); SDL_QuitMainCallbacks(rc);
} }
return (rc == SDL_APP_FAILURE) ? 1 : 0; return (rc == SDL_APP_FAILURE) ? 1 : 0;
} }

View file

@ -75,7 +75,7 @@ int SDL_EnterAppMainCallbacks(int argc, char* argv[], SDL_AppInit_func appinit,
SDL_RemoveHintCallback(SDL_HINT_MAIN_CALLBACK_RATE, MainCallbackRateHintChanged, NULL); SDL_RemoveHintCallback(SDL_HINT_MAIN_CALLBACK_RATE, MainCallbackRateHintChanged, NULL);
} }
SDL_QuitMainCallbacks(); SDL_QuitMainCallbacks(rc);
return (rc == SDL_APP_FAILURE) ? 1 : 0; return (rc == SDL_APP_FAILURE) ? 1 : 0;
} }

View file

@ -55,7 +55,7 @@ static SDLIosMainCallbacksDisplayLink *globalDisplayLink;
[self.displayLink invalidate]; [self.displayLink invalidate];
self.displayLink = nil; self.displayLink = nil;
globalDisplayLink = nil; globalDisplayLink = nil;
SDL_QuitMainCallbacks(); SDL_QuitMainCallbacks(rc);
SDL_UpdateLifecycleObserver(); SDL_UpdateLifecycleObserver();
exit((rc == SDL_APP_FAILURE) ? 1 : 0); exit((rc == SDL_APP_FAILURE) ? 1 : 0);
} }
@ -66,16 +66,18 @@ static SDLIosMainCallbacksDisplayLink *globalDisplayLink;
// When we return from here, we're living in the RunLoop, and a CADisplayLink is firing regularly for us. // When we return from here, we're living in the RunLoop, and a CADisplayLink is firing regularly for us.
int SDL_EnterAppMainCallbacks(int argc, char* argv[], SDL_AppInit_func appinit, SDL_AppIterate_func appiter, SDL_AppEvent_func appevent, SDL_AppQuit_func appquit) int SDL_EnterAppMainCallbacks(int argc, char* argv[], SDL_AppInit_func appinit, SDL_AppIterate_func appiter, SDL_AppEvent_func appevent, SDL_AppQuit_func appquit)
{ {
const SDL_AppResult rc = SDL_InitMainCallbacks(argc, argv, appinit, appiter, appevent, appquit); SDL_AppResult rc = SDL_InitMainCallbacks(argc, argv, appinit, appiter, appevent, appquit);
if (rc == SDL_APP_CONTINUE) { if (rc == SDL_APP_CONTINUE) {
globalDisplayLink = [[SDLIosMainCallbacksDisplayLink alloc] init:appiter quitfunc:appquit]; globalDisplayLink = [[SDLIosMainCallbacksDisplayLink alloc] init:appiter quitfunc:appquit];
if (globalDisplayLink != nil) { if (globalDisplayLink == nil) {
rc = SDL_APP_FAILURE;
} else {
return 0; // this will fall all the way out of SDL_main, where UIApplicationMain will keep running the RunLoop. return 0; // this will fall all the way out of SDL_main, where UIApplicationMain will keep running the RunLoop.
} }
} }
// appinit requested quit, just bounce out now. // appinit requested quit, just bounce out now.
SDL_QuitMainCallbacks(); SDL_QuitMainCallbacks(rc);
exit((rc == SDL_APP_FAILURE) ? 1 : 0); exit((rc == SDL_APP_FAILURE) ? 1 : 0);
return 1; // just in case. return 1; // just in case.

View file

@ -127,7 +127,7 @@ SDL_AppResult SDL_AppIterate(void *appstate)
return fillerup(); return fillerup();
} }
void SDL_AppQuit(void *appstate) void SDL_AppQuit(void *appstate, SDL_AppResult result)
{ {
SDL_DestroyAudioStream(stream); SDL_DestroyAudioStream(stream);
SDL_free(wave.sound); SDL_free(wave.sound);

View file

@ -1256,7 +1256,7 @@ SDL_AppResult SDL_AppIterate(void *appstate)
return SDL_APP_CONTINUE; return SDL_APP_CONTINUE;
} }
void SDL_AppQuit(void *appstate) void SDL_AppQuit(void *appstate, SDL_AppResult result)
{ {
while (things) { while (things) {
DestroyThing(things); /* make sure all the audio devices are closed, etc. */ DestroyThing(things); /* make sure all the audio devices are closed, etc. */

View file

@ -196,7 +196,7 @@ SDL_AppResult SDL_AppIterate(void *appstate)
return SDL_APP_CONTINUE; return SDL_APP_CONTINUE;
} }
void SDL_AppQuit(void *appstate) void SDL_AppQuit(void *appstate, SDL_AppResult result)
{ {
SDL_Log("Shutting down.\n"); SDL_Log("Shutting down.\n");
const SDL_AudioDeviceID devid_in = SDL_GetAudioStreamDevice(stream_in); const SDL_AudioDeviceID devid_in = SDL_GetAudioStreamDevice(stream_in);

View file

@ -353,7 +353,7 @@ SDL_AppResult SDL_AppIterate(void *appstate)
return SDL_APP_CONTINUE; return SDL_APP_CONTINUE;
} }
void SDL_AppQuit(void *appstate) void SDL_AppQuit(void *appstate, SDL_AppResult result)
{ {
SDL_ReleaseCameraFrame(camera, frame_current); SDL_ReleaseCameraFrame(camera, frame_current);
SDL_CloseCamera(camera); SDL_CloseCamera(camera);

View file

@ -114,7 +114,7 @@ SDL_AppResult SDL_AppIterate(void *appstate)
return SDL_APP_CONTINUE; return SDL_APP_CONTINUE;
} }
void SDL_AppQuit(void *appstate) void SDL_AppQuit(void *appstate, SDL_AppResult result)
{ {
dropfile_dialog *dialog = appstate; dropfile_dialog *dialog = appstate;
if (dialog) { if (dialog) {

View file

@ -110,7 +110,7 @@ SDL_AppResult SDL_AppIterate(void *appstate)
return SDL_APP_CONTINUE; return SDL_APP_CONTINUE;
} }
void SDL_AppQuit(void *appstate) void SDL_AppQuit(void *appstate, SDL_AppResult result)
{ {
/* Print out some timing information */ /* Print out some timing information */
const Uint64 now = SDL_GetTicks(); const Uint64 now = SDL_GetTicks();

View file

@ -273,7 +273,7 @@ SDL_AppResult SDL_AppIterate(void *appstate)
return SDL_APP_CONTINUE; return SDL_APP_CONTINUE;
} }
void SDL_AppQuit(void *appstate) void SDL_AppQuit(void *appstate, SDL_AppResult result)
{ {
Pen *i, *next; Pen *i, *next;
for (i = pens.next; i != NULL; i = next) { for (i = pens.next; i != NULL; i = next) {

View file

@ -42,7 +42,7 @@ static bool suspend_when_occluded;
/* -1: infinite random moves (default); >=0: enables N deterministic moves */ /* -1: infinite random moves (default); >=0: enables N deterministic moves */
static int iterations = -1; static int iterations = -1;
void SDL_AppQuit(void *appstate) void SDL_AppQuit(void *appstate, SDL_AppResult result)
{ {
SDL_free(sprites); SDL_free(sprites);
SDL_free(positions); SDL_free(positions);