From 9caff407f4fd5b155c4f02975da1fe36df11e9d0 Mon Sep 17 00:00:00 2001 From: Scott Duensing Date: Sun, 21 Dec 2025 20:51:59 -0600 Subject: [PATCH] Threaded apps are starting to work. --- roo_e/main.c | 134 ++++++++++++++++++++++++++++++++------------------ roo_e/roo_e.h | 14 +++++- 2 files changed, 99 insertions(+), 49 deletions(-) diff --git a/roo_e/main.c b/roo_e/main.c index 175163e..4175daf 100644 --- a/roo_e/main.c +++ b/roo_e/main.c @@ -26,7 +26,10 @@ #include "roo_e.h" -static RooNamedPointerT **_appList = NULL; // NOLINT +static RooAppThreadT **_appThreadList = NULL; // NOLINT + + +static void *rooStartAppThread(void *arg); #ifdef PLATFORM_DOS @@ -120,37 +123,56 @@ static int lastResort(void) { #endif // PLATFORM_DOS -int rooStartApp(const char *appName, const int argc, char *argv[], RooNamedPointerT **handle) { - RooNamedPointerT *namedPointer = NULL; - int result = -1; - int (*appMain)(const int argc, char *argv[]); // NOLINT +RooAppThreadT *rooStartApp(const char *appName, const int argc, char *argv[]) { + RooAppThreadT *appThread = NULL; + + dlerror(); // Clear any existing error. + NEW(RooAppThreadT, appThread); + NEW(RooNamedPointerT, appThread->namedPointer); + appThread->namedPointer->name = utilCreateString("app/%s.app", appName); + appThread->namedPointer->pointer = dlopen(appThread->namedPointer->name, RTLD_LAZY); + if (!appThread->namedPointer->pointer) { + printf("ROO/E: Unable to load %s! %s\n", appThread->namedPointer->name, dlerror()); + DEL(appThread->namedPointer->name); + DEL(appThread->namedPointer); + DEL(appThread); + } else { + appThread->argc = argc; + //***TODO*** argv handling is a bit sketchy. We should deep copy this. + appThread->argv = argv; + appThread->result = -1; + pthread_create(&appThread->thread, NULL, rooStartAppThread, (void *)appThread); + arrput(_appThreadList, appThread); + } + + return appThread; +} + + +static void *rooStartAppThread(void *arg) { + int (*appMain)(const int argc, char *argv[]); // NOLINT + RooAppThreadT *appThread = (RooAppThreadT *)arg; union { void *from; int (*to)(const int argc, char *argv[]); } appPtrCast; // NOLINT - dlerror(); // Clear any existing error. - NEW(RooNamedPointerT, namedPointer); - namedPointer->name = utilCreateString("app/%s.app", appName); - namedPointer->pointer = dlopen(namedPointer->name, RTLD_LAZY); - if (!namedPointer->pointer) { - printf("ROO/E: Unable to load %s! %s\n", namedPointer->name, dlerror()); - } else { - appPtrCast.from = dlsym(namedPointer->pointer, "_appMain"); - appMain = appPtrCast.to; // NOLINT - result = appMain(argc, argv); - arrput(_appList, namedPointer); - if (handle != NULL) *handle = namedPointer->pointer; - } + appThread->running = true; + appPtrCast.from = dlsym(appThread->namedPointer->pointer, "_appMain"); + appMain = appPtrCast.to; // NOLINT + debug("ROO/E: Calling appMain.\n"); + appThread->result = appMain(appThread->argc, appThread->argv); + debug("ROO/E: Back from appMain.\n"); + appThread->running = false; - return result; + return NULL; } -RooAbortReasonT rooStopApp(RooNamedPointerT **appHandle, RooStopReasonT reason) { +RooAbortReasonT rooStopApp(RooAppThreadT **threadPointer, RooStopReasonT reason) { RooAbortReasonT abort = ROO_ABORT_NONE; - RooNamedPointerT *namedPointer = NULL; + RooAppThreadT *appThread = NULL; int (*appStop)(RooStopReasonT reason); union { @@ -158,17 +180,12 @@ RooAbortReasonT rooStopApp(RooNamedPointerT **appHandle, RooStopReasonT reason) int (*to)(RooStopReasonT reason); } appPtrCast; // NOLINT - namedPointer = *appHandle; + appThread = *threadPointer; - appPtrCast.from = dlsym(namedPointer->pointer, "_appStop"); + appPtrCast.from = dlsym(appThread->namedPointer->pointer, "_appStop"); if (appPtrCast.from != NULL) { appStop = appPtrCast.to; // NOLINT - abort = appStop(reason); - } - if (abort == ROO_ABORT_NONE) { - dlclose(namedPointer->pointer); - DEL(namedPointer->name); - DEL(namedPointer); + abort = appStop(reason); } return abort; @@ -177,13 +194,15 @@ RooAbortReasonT rooStopApp(RooNamedPointerT **appHandle, RooStopReasonT reason) int main(const int argc, char *argv[]) { - DIR *dir = NULL; - struct dirent *dirent = NULL; + DIR *dir = NULL; + struct dirent *dirent = NULL; + RooAppThreadT *appThread = NULL;; + RooNamedPointerT **dynList = NULL; + RooNamedPointerT *namedPointer = NULL; int result; - RooAbortReasonT abort; - RooNamedPointerT **dynList = NULL; - RooNamedPointerT *namedPointer = NULL; - int (*dynInitStop)(void); +// RooAbortReasonT abort; + int x; + int (*dynInitStop)(void); union { void *from; @@ -237,25 +256,46 @@ int main(const int argc, char *argv[]) { debug("ROO/E: Loaded %d libraries.\n", arrlen(dynList)); // Load the Shell. This needs to be configurable. - result = rooStartApp("kpsmpgc", 0, NULL, NULL); + rooStartApp("kpsmpgc", 0, NULL); // Run as long as apps are running. - while (arrlen(_appList) > 0) { + while (arrlen(_appThreadList) > 0) { // Wait for all apps to exit. - - // Unload APPs. - while (arrlen(_appList) > 0) { - namedPointer = _appList[0]; // NOLINT - debug("ROO/E: Stopping %s\n", namedPointer->name); - abort = rooStopApp(&namedPointer, ROO_STOP_SHUTDOWN); - if (abort == ROO_ABORT_NONE) { - arrdel(_appList, 0); - } else { - break; // Somebody didn't want to stop. + for (x=0; xrunning); + if (appThread->running == false) { + debug("ROO/E: Joining.\n"); + pthread_join(appThread->thread, NULL); + debug("ROO/E: Joined.\n"); + dlclose(appThread->namedPointer->pointer); + debug("ROO/E: %s exited.\n", appThread->namedPointer->name); + DEL(appThread->namedPointer->name); + DEL(appThread->namedPointer); + //***TODO*** Deal with argv cleanup here? + DEL(appThread); + //***TODO*** We need some way to deal with return values and checking if apps are alive. + arrdel(_appThreadList, x); + // Exit loop after changing array length. + break; } } } + /* + // Unload APPs. + while (arrlen(_appThreadList) > 0) { + appThread = _appThreadList[0]; // NOLINT + debug("ROO/E: Stopping %s\n", appThread->namedPointer->name); + abort = rooStopApp(&appThread, ROO_STOP_SHUTDOWN); + if (abort == ROO_ABORT_NONE) { + arrdel(_appThreadList, 0); + } else { + break; // Somebody didn't want to stop. + } + } + */ + // Unload DYNs debug("ROO/E: Unloading %d libraries.\n", arrlen(dynList)); while (arrlen(dynList) > 0) { diff --git a/roo_e/roo_e.h b/roo_e/roo_e.h index 37b7662..8535e29 100644 --- a/roo_e/roo_e.h +++ b/roo_e/roo_e.h @@ -51,6 +51,16 @@ typedef struct RooNamedPointerS { void *pointer; } RooNamedPointerT; +typedef struct RooAppThreadS { + pthread_t thread; + volatile bool running; + int argc; + char **argv; + int result; + RooNamedPointerT *namedPointer; +} RooAppThreadT; + + typedef enum { ROO_STOP_EXITING = 0, // App quit ROO_STOP_SHUTDOWN, // Roo/E shutdown @@ -64,8 +74,8 @@ typedef enum { } RooAbortReasonT; -int rooStartApp(const char *appName, int argc, char *argv[], RooNamedPointerT **handle); -RooAbortReasonT rooStopApp(RooNamedPointerT **appHandle, RooStopReasonT reason); +RooAppThreadT *rooStartApp(const char *appName, int argc, char *argv[]); +RooAbortReasonT rooStopApp(RooAppThreadT **threadPointer, RooStopReasonT reason); #endif // ROO_E_H