Threaded apps are starting to work.

This commit is contained in:
Scott Duensing 2025-12-21 20:51:59 -06:00
parent f28bbd476e
commit 9caff407f4
2 changed files with 99 additions and 49 deletions

View file

@ -26,7 +26,10 @@
#include "roo_e.h" #include "roo_e.h"
static RooNamedPointerT **_appList = NULL; // NOLINT static RooAppThreadT **_appThreadList = NULL; // NOLINT
static void *rooStartAppThread(void *arg);
#ifdef PLATFORM_DOS #ifdef PLATFORM_DOS
@ -120,37 +123,56 @@ static int lastResort(void) {
#endif // PLATFORM_DOS #endif // PLATFORM_DOS
int rooStartApp(const char *appName, const int argc, char *argv[], RooNamedPointerT **handle) { RooAppThreadT *rooStartApp(const char *appName, const int argc, char *argv[]) {
RooNamedPointerT *namedPointer = NULL; RooAppThreadT *appThread = NULL;
int result = -1;
int (*appMain)(const int argc, char *argv[]); // NOLINT 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 { union {
void *from; void *from;
int (*to)(const int argc, char *argv[]); int (*to)(const int argc, char *argv[]);
} appPtrCast; // NOLINT } appPtrCast; // NOLINT
dlerror(); // Clear any existing error. appThread->running = true;
NEW(RooNamedPointerT, namedPointer); appPtrCast.from = dlsym(appThread->namedPointer->pointer, "_appMain");
namedPointer->name = utilCreateString("app/%s.app", appName); appMain = appPtrCast.to; // NOLINT
namedPointer->pointer = dlopen(namedPointer->name, RTLD_LAZY); debug("ROO/E: Calling appMain.\n");
if (!namedPointer->pointer) { appThread->result = appMain(appThread->argc, appThread->argv);
printf("ROO/E: Unable to load %s! %s\n", namedPointer->name, dlerror()); debug("ROO/E: Back from appMain.\n");
} else { appThread->running = false;
appPtrCast.from = dlsym(namedPointer->pointer, "_appMain");
appMain = appPtrCast.to; // NOLINT
result = appMain(argc, argv);
arrput(_appList, namedPointer);
if (handle != NULL) *handle = namedPointer->pointer;
}
return result; return NULL;
} }
RooAbortReasonT rooStopApp(RooNamedPointerT **appHandle, RooStopReasonT reason) { RooAbortReasonT rooStopApp(RooAppThreadT **threadPointer, RooStopReasonT reason) {
RooAbortReasonT abort = ROO_ABORT_NONE; RooAbortReasonT abort = ROO_ABORT_NONE;
RooNamedPointerT *namedPointer = NULL; RooAppThreadT *appThread = NULL;
int (*appStop)(RooStopReasonT reason); int (*appStop)(RooStopReasonT reason);
union { union {
@ -158,17 +180,12 @@ RooAbortReasonT rooStopApp(RooNamedPointerT **appHandle, RooStopReasonT reason)
int (*to)(RooStopReasonT reason); int (*to)(RooStopReasonT reason);
} appPtrCast; // NOLINT } appPtrCast; // NOLINT
namedPointer = *appHandle; appThread = *threadPointer;
appPtrCast.from = dlsym(namedPointer->pointer, "_appStop"); appPtrCast.from = dlsym(appThread->namedPointer->pointer, "_appStop");
if (appPtrCast.from != NULL) { if (appPtrCast.from != NULL) {
appStop = appPtrCast.to; // NOLINT appStop = appPtrCast.to; // NOLINT
abort = appStop(reason); abort = appStop(reason);
}
if (abort == ROO_ABORT_NONE) {
dlclose(namedPointer->pointer);
DEL(namedPointer->name);
DEL(namedPointer);
} }
return abort; return abort;
@ -177,13 +194,15 @@ RooAbortReasonT rooStopApp(RooNamedPointerT **appHandle, RooStopReasonT reason)
int main(const int argc, char *argv[]) { int main(const int argc, char *argv[]) {
DIR *dir = NULL; DIR *dir = NULL;
struct dirent *dirent = NULL; struct dirent *dirent = NULL;
RooAppThreadT *appThread = NULL;;
RooNamedPointerT **dynList = NULL;
RooNamedPointerT *namedPointer = NULL;
int result; int result;
RooAbortReasonT abort; // RooAbortReasonT abort;
RooNamedPointerT **dynList = NULL; int x;
RooNamedPointerT *namedPointer = NULL; int (*dynInitStop)(void);
int (*dynInitStop)(void);
union { union {
void *from; void *from;
@ -237,25 +256,46 @@ int main(const int argc, char *argv[]) {
debug("ROO/E: Loaded %d libraries.\n", arrlen(dynList)); debug("ROO/E: Loaded %d libraries.\n", arrlen(dynList));
// Load the Shell. This needs to be configurable. // 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. // Run as long as apps are running.
while (arrlen(_appList) > 0) { while (arrlen(_appThreadList) > 0) {
// Wait for all apps to exit. // Wait for all apps to exit.
for (x=0; x<arrlen(_appThreadList); x++) {
// Unload APPs. appThread = _appThreadList[x]; // NOLINT
while (arrlen(_appList) > 0) { debug("ROO/E: App %d of %d running == %d\n", x, arrlen(_appThreadList), (int)appThread->running);
namedPointer = _appList[0]; // NOLINT if (appThread->running == false) {
debug("ROO/E: Stopping %s\n", namedPointer->name); debug("ROO/E: Joining.\n");
abort = rooStopApp(&namedPointer, ROO_STOP_SHUTDOWN); pthread_join(appThread->thread, NULL);
if (abort == ROO_ABORT_NONE) { debug("ROO/E: Joined.\n");
arrdel(_appList, 0); dlclose(appThread->namedPointer->pointer);
} else { debug("ROO/E: %s exited.\n", appThread->namedPointer->name);
break; // Somebody didn't want to stop. 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 // Unload DYNs
debug("ROO/E: Unloading %d libraries.\n", arrlen(dynList)); debug("ROO/E: Unloading %d libraries.\n", arrlen(dynList));
while (arrlen(dynList) > 0) { while (arrlen(dynList) > 0) {

View file

@ -51,6 +51,16 @@ typedef struct RooNamedPointerS {
void *pointer; void *pointer;
} RooNamedPointerT; } RooNamedPointerT;
typedef struct RooAppThreadS {
pthread_t thread;
volatile bool running;
int argc;
char **argv;
int result;
RooNamedPointerT *namedPointer;
} RooAppThreadT;
typedef enum { typedef enum {
ROO_STOP_EXITING = 0, // App quit ROO_STOP_EXITING = 0, // App quit
ROO_STOP_SHUTDOWN, // Roo/E shutdown ROO_STOP_SHUTDOWN, // Roo/E shutdown
@ -64,8 +74,8 @@ typedef enum {
} RooAbortReasonT; } RooAbortReasonT;
int rooStartApp(const char *appName, int argc, char *argv[], RooNamedPointerT **handle); RooAppThreadT *rooStartApp(const char *appName, int argc, char *argv[]);
RooAbortReasonT rooStopApp(RooNamedPointerT **appHandle, RooStopReasonT reason); RooAbortReasonT rooStopApp(RooAppThreadT **threadPointer, RooStopReasonT reason);
#endif // ROO_E_H #endif // ROO_E_H