dlopen edge case for non-multi-instance apps avoided.
This commit is contained in:
parent
fc3a513ada
commit
1e59499529
1 changed files with 18 additions and 23 deletions
|
|
@ -32,7 +32,7 @@ static void appTaskWrapper(void *arg);
|
||||||
static const char *baseName(const char *path);
|
static const char *baseName(const char *path);
|
||||||
static void cleanupTempFile(ShellAppT *app);
|
static void cleanupTempFile(ShellAppT *app);
|
||||||
static int32_t copyFile(const char *src, const char *dst);
|
static int32_t copyFile(const char *src, const char *dst);
|
||||||
static bool isPathLoaded(const char *path);
|
static ShellAppT *findLoadedPath(const char *path);
|
||||||
static int32_t makeTempPath(const char *origPath, int32_t id, char *out, int32_t outSize);
|
static int32_t makeTempPath(const char *origPath, int32_t id, char *out, int32_t outSize);
|
||||||
void shellAppInit(void);
|
void shellAppInit(void);
|
||||||
void shellForceKillApp(AppContextT *ctx, ShellAppT *app);
|
void shellForceKillApp(AppContextT *ctx, ShellAppT *app);
|
||||||
|
|
@ -135,15 +135,16 @@ static int32_t copyFile(const char *src, const char *dst) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Check if a DXE path is already loaded in any active slot.
|
// Find an active slot with the given DXE path. Returns the slot pointer,
|
||||||
static bool isPathLoaded(const char *path) {
|
// or NULL if no running app was loaded from this path.
|
||||||
|
static ShellAppT *findLoadedPath(const char *path) {
|
||||||
for (int32_t i = 1; i < SHELL_MAX_APPS; i++) {
|
for (int32_t i = 1; i < SHELL_MAX_APPS; i++) {
|
||||||
if (sApps[i].state != AppStateFreeE && strcmp(sApps[i].path, path) == 0) {
|
if (sApps[i].state != AppStateFreeE && strcmp(sApps[i].path, path) == 0) {
|
||||||
return true;
|
return &sApps[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -264,29 +265,23 @@ int32_t shellLoadApp(AppContextT *ctx, const char *path) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if this DXE is already loaded. If so, we need to inspect its
|
// Check if this DXE is already loaded. If so, check whether the app
|
||||||
// descriptor to decide whether to allow a second instance.
|
// allows multiple instances. We read the descriptor from the existing
|
||||||
|
// slot directly — no need to dlopen again.
|
||||||
const char *loadPath = path;
|
const char *loadPath = path;
|
||||||
char tempPath[260] = {0};
|
char tempPath[260] = {0};
|
||||||
|
ShellAppT *existing = findLoadedPath(path);
|
||||||
|
|
||||||
if (isPathLoaded(path)) {
|
if (existing) {
|
||||||
// Peek at the descriptor from the already-loaded module to check
|
// Read multiInstance from the already-loaded descriptor
|
||||||
// multiInstance. Since it's already loaded, dlopen returns the
|
AppDescriptorT *existDesc = (AppDescriptorT *)dlsym(existing->dxeHandle, "_appDescriptor");
|
||||||
// existing handle (cheap, no actual reload).
|
|
||||||
void *peek = dlopen(path, RTLD_GLOBAL);
|
|
||||||
|
|
||||||
if (peek) {
|
if (!existDesc || !existDesc->multiInstance) {
|
||||||
AppDescriptorT *peekDesc = (AppDescriptorT *)dlsym(peek, "_appDescriptor");
|
|
||||||
bool allow = peekDesc && peekDesc->multiInstance;
|
|
||||||
dlclose(peek);
|
|
||||||
|
|
||||||
if (!allow) {
|
|
||||||
char msg[320];
|
char msg[320];
|
||||||
snprintf(msg, sizeof(msg), "%s is already running.", baseName(path));
|
snprintf(msg, sizeof(msg), "%s is already running.", baseName(path));
|
||||||
dvxMessageBox(ctx, "Error", msg, MB_OK | MB_ICONERROR);
|
dvxMessageBox(ctx, "Error", msg, MB_OK | MB_ICONERROR);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Multi-instance allowed: copy to a temp file so dlopen gets
|
// Multi-instance allowed: copy to a temp file so dlopen gets
|
||||||
// an independent code+data image.
|
// an independent code+data image.
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue