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 void cleanupTempFile(ShellAppT *app);
|
||||
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);
|
||||
void shellAppInit(void);
|
||||
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.
|
||||
static bool isPathLoaded(const char *path) {
|
||||
// Find an active slot with the given DXE path. Returns the slot pointer,
|
||||
// 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++) {
|
||||
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;
|
||||
}
|
||||
|
||||
// Check if this DXE is already loaded. If so, we need to inspect its
|
||||
// descriptor to decide whether to allow a second instance.
|
||||
// Check if this DXE is already loaded. If so, check whether the app
|
||||
// allows multiple instances. We read the descriptor from the existing
|
||||
// slot directly — no need to dlopen again.
|
||||
const char *loadPath = path;
|
||||
char tempPath[260] = {0};
|
||||
ShellAppT *existing = findLoadedPath(path);
|
||||
|
||||
if (isPathLoaded(path)) {
|
||||
// Peek at the descriptor from the already-loaded module to check
|
||||
// multiInstance. Since it's already loaded, dlopen returns the
|
||||
// existing handle (cheap, no actual reload).
|
||||
void *peek = dlopen(path, RTLD_GLOBAL);
|
||||
if (existing) {
|
||||
// Read multiInstance from the already-loaded descriptor
|
||||
AppDescriptorT *existDesc = (AppDescriptorT *)dlsym(existing->dxeHandle, "_appDescriptor");
|
||||
|
||||
if (peek) {
|
||||
AppDescriptorT *peekDesc = (AppDescriptorT *)dlsym(peek, "_appDescriptor");
|
||||
bool allow = peekDesc && peekDesc->multiInstance;
|
||||
dlclose(peek);
|
||||
|
||||
if (!allow) {
|
||||
if (!existDesc || !existDesc->multiInstance) {
|
||||
char msg[320];
|
||||
snprintf(msg, sizeof(msg), "%s is already running.", baseName(path));
|
||||
dvxMessageBox(ctx, "Error", msg, MB_OK | MB_ICONERROR);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// Multi-instance allowed: copy to a temp file so dlopen gets
|
||||
// an independent code+data image.
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue