about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2021-03-25 11:36:14 +0100
committerptitSeb <sebastien.chev@gmail.com>2021-03-25 11:36:14 +0100
commit72ca99051b9ea5786e22214d2cbb0befd70be670 (patch)
tree03ff3001d6097a6aa0a7d1cfc4c19ed037fc41c6 /src
parent905e3ae583da508c24dbb80628fb08084e62ae80 (diff)
downloadbox64-72ca99051b9ea5786e22214d2cbb0befd70be670.tar.gz
box64-72ca99051b9ea5786e22214d2cbb0befd70be670.zip
Improved shutdown sequence
Diffstat (limited to 'src')
-rwxr-xr-xsrc/box64context.c10
-rwxr-xr-xsrc/elfs/elfloader.c2
-rwxr-xr-xsrc/include/librarian.h2
-rwxr-xr-xsrc/include/library.h2
-rwxr-xr-xsrc/librarian/librarian.c6
-rwxr-xr-xsrc/librarian/library.c19
-rwxr-xr-xsrc/main.c46
7 files changed, 69 insertions, 18 deletions
diff --git a/src/box64context.c b/src/box64context.c
index 91aa4fbc..f020191e 100755
--- a/src/box64context.c
+++ b/src/box64context.c
@@ -129,16 +129,16 @@ void FreeBox64Context(box64context_t** context)
 
     box64context_t* ctx = *context;   // local copy to do the cleanning
 
+    if(ctx->local_maplib)
+        FreeLibrarian(&ctx->local_maplib, NULL);
+    if(ctx->maplib)
+        FreeLibrarian(&ctx->maplib, NULL);
+
     for(int i=0; i<ctx->elfsize; ++i) {
         FreeElfHeader(&ctx->elfs[i]);
     }
     free(ctx->elfs);
 
-    if(ctx->maplib)
-        FreeLibrarian(&ctx->maplib);
-    if(ctx->local_maplib)
-        FreeLibrarian(&ctx->local_maplib);
-
     FreeCollection(&ctx->box64_path);
     FreeCollection(&ctx->box64_ld_lib);
     FreeCollection(&ctx->box64_emulated_libs);
diff --git a/src/elfs/elfloader.c b/src/elfs/elfloader.c
index 52aab63e..652ec253 100755
--- a/src/elfs/elfloader.c
+++ b/src/elfs/elfloader.c
@@ -1097,7 +1097,7 @@ const char* FindNearestSymbolName(elfheader_t* h, void* p, uintptr_t* start, uin
     const char* ret = NULL;
     uintptr_t s = 0;
     uint32_t size = 0;
-    if(!h)
+    if(!h || h->fini_done)
         return ret;
 
     for (int i=0; i<h->numSymTab && distance!=0; ++i) {   
diff --git a/src/include/librarian.h b/src/include/librarian.h
index a25fcd7b..f63b500f 100755
--- a/src/include/librarian.h
+++ b/src/include/librarian.h
@@ -15,7 +15,7 @@ typedef struct kh_mapoffsets_s kh_mapoffsets_t;
 typedef char* cstr_t;
 
 lib_t *NewLibrarian(box64context_t* context, int ownlibs);
-void FreeLibrarian(lib_t **maplib);
+void FreeLibrarian(lib_t **maplib, x64emu_t* emu);
 dlprivate_t *NewDLPrivate();
 void FreeDLPrivate(dlprivate_t **lib);
 
diff --git a/src/include/library.h b/src/include/library.h
index d33b1126..9af07c34 100755
--- a/src/include/library.h
+++ b/src/include/library.h
@@ -14,7 +14,7 @@ int AddSymbolsLibrary(lib_t* maplib, library_t* lib, x64emu_t* emu);
 int FinalizeLibrary(library_t* lib, lib_t* local_maplib, x64emu_t* emu);
 int ReloadLibrary(library_t* lib, x64emu_t* emu);
 void InactiveLibrary(library_t* lib);
-void Free1Library(library_t **lib);
+void Free1Library(library_t **lib, x64emu_t* emu);
 
 char* GetNameLib(library_t *lib);
 int IsSameLib(library_t* lib, const char* path);    // check if lib is same (path -> name)
diff --git a/src/librarian/librarian.c b/src/librarian/librarian.c
index dcfe4754..f7f3756a 100755
--- a/src/librarian/librarian.c
+++ b/src/librarian/librarian.c
@@ -34,7 +34,7 @@ lib_t *NewLibrarian(box64context_t* context, int ownlibs)
 
     return maplib;
 }
-void FreeLibrarian(lib_t **maplib)
+void FreeLibrarian(lib_t **maplib, x64emu_t *emu)
 {
     // should that be in reverse order?
     if(!maplib || !*maplib)
@@ -42,9 +42,9 @@ void FreeLibrarian(lib_t **maplib)
     
     if((*maplib)->ownlibs) {
         printf_log(LOG_DEBUG, "Closing %d libs from maplib %p\n", (*maplib)->libsz, *maplib);
-        for (int i=0; i<(*maplib)->libsz; ++i) {
+        for (int i=(*maplib)->libsz-1; i>=0; --i) {
             printf_log(LOG_DEBUG, "Unloading %s\n", (*maplib)->libraries[i].lib->name);
-            Free1Library(&(*maplib)->libraries[i].lib);
+            Free1Library(&(*maplib)->libraries[i].lib, emu);
         }
     }
     free((*maplib)->libraries);
diff --git a/src/librarian/library.c b/src/librarian/library.c
index b0be60b4..bd85b8cf 100755
--- a/src/librarian/library.c
+++ b/src/librarian/library.c
@@ -246,13 +246,13 @@ library_t *NewLibrary(const char* path, box64context_t* context)
     printf_log(LOG_DEBUG, "Simplified name is \"%s\"\n", lib->name);
     if(box64_nopulse) {
         if(strstr(lib->name, "libpulse.so")==lib->name || strstr(lib->name, "libpulse-simple.so")==lib->name) {
-            Free1Library(&lib);
+            Free1Library(&lib, NULL);
             return NULL;
         }
     }
     if(box64_novulkan) {
         if(strstr(lib->name, "libvulkan.so")==lib->name) {
-            Free1Library(&lib);
+            Free1Library(&lib, NULL);
             return NULL;
         }
     }
@@ -270,7 +270,7 @@ library_t *NewLibrary(const char* path, box64context_t* context)
     // nothing loaded, so error...
     if(lib->type==-1)
     {
-        Free1Library(&lib);
+        Free1Library(&lib, NULL);
         return NULL;
     }
 
@@ -375,10 +375,18 @@ void InactiveLibrary(library_t* lib)
     lib->active = 0;
 }
 
-void Free1Library(library_t **lib)
+void Free1Library(library_t **lib, x64emu_t* emu)
 {
     if(!(*lib)) return;
 
+    if((*lib)->type==1 && emu) {
+        elfheader_t *elf_header = (*lib)->context->elfs[(*lib)->priv.n.elf_index];
+        RunElfFini(elf_header, emu);
+    }
+
+    if((*lib)->maplib)
+        FreeLibrarian(&(*lib)->maplib, emu);
+
     if((*lib)->type!=-1 && (*lib)->fini) {
         (*lib)->fini(*lib);
     }
@@ -411,9 +419,6 @@ void Free1Library(library_t **lib)
         kh_destroy(symbol2map, (*lib)->symbol2map);
     free_neededlib(&(*lib)->needed);
 
-    if((*lib)->maplib)
-        FreeLibrarian(&(*lib)->maplib);
-
     free(*lib);
     *lib = NULL;
 }
diff --git a/src/main.c b/src/main.c
index c14591b0..66bfd94d 100755
--- a/src/main.c
+++ b/src/main.c
@@ -589,6 +589,52 @@ void endBox64()
     if(!my_context)
         return;
 
+    x64emu_t* emu = thread_get_emu();
+    //atexit first
+    printf_log(LOG_DEBUG, "Calling atexit registered functions\n");
+    CallAllCleanup(emu);
+    // than call all the Fini (some "smart" ordering of the fini may be needed, but for now, callign in this order should be good enough)
+    printf_log(LOG_DEBUG, "Calling fini for all loaded elfs and unload native libs\n");
+    RunElfFini(my_context->elfs[0], emu);
+    FreeLibrarian(&my_context->maplib, emu);    // unload all libs
+    FreeLibrarian(&my_context->local_maplib, emu);    // unload all libs
+    // waiting for all thread except this one to finish
+    int this_thread = GetTID();
+    int pid = getpid();
+    int running = 1;
+    int attempt = 0;
+    printf_log(LOG_DEBUG, "Waiting for all threads to finish before unloading box86context\n");
+    while(running) {
+        DIR *proc_dir;
+        char dirname[100];
+        snprintf(dirname, sizeof dirname, "/proc/self/task");
+        proc_dir = opendir(dirname);
+        running = 0;
+        if (proc_dir)
+        {
+            struct dirent *entry;
+            while ((entry = readdir(proc_dir)) != NULL && !running)
+            {
+                if(entry->d_name[0] == '.')
+                    continue;
+
+                int tid = atoi(entry->d_name);
+                // tid != pthread_t, so no pthread functions are available here
+                if(tid!=this_thread) {
+                    if(attempt>4000) {
+                        printf_log(LOG_INFO, "Stop waiting for remaining thread %04d\n", tid);
+                        // enough wait, kill all thread!
+                        syscall(__NR_tgkill, pid, tid, SIGABRT);
+                    } else {
+                        running = 1;
+                        ++attempt;
+                        sched_yield();
+                    }
+                }
+            }
+            closedir(proc_dir);
+        }
+    }
     // all done, free context
     FreeBox64Context(&my_context);
     if(libGL) {