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"
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; x<arrlen(_appThreadList); x++) {
appThread = _appThreadList[x]; // NOLINT
debug("ROO/E: App %d of %d running == %d\n", x, arrlen(_appThreadList), (int)appThread->running);
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) {

View file

@ -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