Threaded apps are starting to work.
This commit is contained in:
parent
f28bbd476e
commit
9caff407f4
2 changed files with 99 additions and 49 deletions
112
roo_e/main.c
112
roo_e/main.c
|
|
@ -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;
|
|
||||||
|
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
|
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);
|
|
||||||
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
|
appMain = appPtrCast.to; // NOLINT
|
||||||
result = appMain(argc, argv);
|
debug("ROO/E: Calling appMain.\n");
|
||||||
arrput(_appList, namedPointer);
|
appThread->result = appMain(appThread->argc, appThread->argv);
|
||||||
if (handle != NULL) *handle = namedPointer->pointer;
|
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;
|
RooAbortReasonT abort = ROO_ABORT_NONE;
|
||||||
RooNamedPointerT *namedPointer = NULL;
|
RooAppThreadT *appThread = NULL;
|
||||||
int (*appStop)(RooStopReasonT reason);
|
int (*appStop)(RooStopReasonT reason);
|
||||||
|
|
||||||
union {
|
union {
|
||||||
|
|
@ -158,18 +180,13 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
@ -179,10 +196,12 @@ int main(const int argc, char *argv[]) {
|
||||||
|
|
||||||
DIR *dir = NULL;
|
DIR *dir = NULL;
|
||||||
struct dirent *dirent = NULL;
|
struct dirent *dirent = NULL;
|
||||||
int result;
|
RooAppThreadT *appThread = NULL;;
|
||||||
RooAbortReasonT abort;
|
|
||||||
RooNamedPointerT **dynList = NULL;
|
RooNamedPointerT **dynList = NULL;
|
||||||
RooNamedPointerT *namedPointer = NULL;
|
RooNamedPointerT *namedPointer = NULL;
|
||||||
|
int result;
|
||||||
|
// RooAbortReasonT abort;
|
||||||
|
int x;
|
||||||
int (*dynInitStop)(void);
|
int (*dynInitStop)(void);
|
||||||
|
|
||||||
union {
|
union {
|
||||||
|
|
@ -237,24 +256,45 @@ 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++) {
|
||||||
|
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.
|
// Unload APPs.
|
||||||
while (arrlen(_appList) > 0) {
|
while (arrlen(_appThreadList) > 0) {
|
||||||
namedPointer = _appList[0]; // NOLINT
|
appThread = _appThreadList[0]; // NOLINT
|
||||||
debug("ROO/E: Stopping %s\n", namedPointer->name);
|
debug("ROO/E: Stopping %s\n", appThread->namedPointer->name);
|
||||||
abort = rooStopApp(&namedPointer, ROO_STOP_SHUTDOWN);
|
abort = rooStopApp(&appThread, ROO_STOP_SHUTDOWN);
|
||||||
if (abort == ROO_ABORT_NONE) {
|
if (abort == ROO_ABORT_NONE) {
|
||||||
arrdel(_appList, 0);
|
arrdel(_appThreadList, 0);
|
||||||
} else {
|
} else {
|
||||||
break; // Somebody didn't want to stop.
|
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));
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue