Fix post-GC crash in enter-foreign-callback

Resulting from change 338c975d
This commit is contained in:
Douglas Katzman 2020-09-09 00:09:40 -04:00
parent 8e275cc17c
commit 8614c726b6
3 changed files with 53 additions and 5 deletions

View file

@ -254,8 +254,12 @@ statistics are appended to it."
;;
;; KLUDGE: Don't run the hooks in GC's if:
;;
;; A) this thread is dying, so that user-code never runs with
;; (thread-alive-p *current-thread*) => nil
;; A) this thread is dying or just born, so that user-code never runs with
;; (thread-alive-p *current-thread*) => nil.
;; The just-born case can happen with foreign threads that are unlucky
;; enough to be elected to perform GC just as they begin executing
;; ENTER-FOREIGN-CALLBACK. This definitely seems to happen with sb-safepoint.
;; I'm not sure whether it can happen without sb-safepoint.
;;
;; B) interrupts are disabled somewhere up the call chain since we
;; don't want to run user code in such a case.
@ -266,7 +270,10 @@ statistics are appended to it."
;; but it's not permissible to invoke CONDITION-NOTIFY from a
;; dying thread, so we still need the guard for that, but not
;; the guard for whether interupts are enabled.
(when (sb-thread:thread-alive-p sb-thread:*current-thread*)
(when (and
#+sb-thread (/= 0 (sap-int (sb-vm::current-thread-offset-sap
sb-vm::thread-lisp-thread-slot)))
(sb-thread:thread-alive-p sb-thread:*current-thread*))
#+sb-thread (alien-funcall (extern-alien "empty_thread_recyclebin" (function void)))
(let ((threadp #+sb-thread (%instancep sb-impl::*finalizer-thread*)))
(when threadp

View file

@ -4,6 +4,7 @@
#ifdef _WIN32
# include <handleapi.h>
# include <process.h>
# include <processthreadsapi.h>
# include <synchapi.h> // for WaitForSingleObject
#else
@ -22,7 +23,39 @@ char *salutations[8] = {
int sharedvar;
#ifdef _WIN32
long unsigned int doThatThing(void* void_arg)
__stdcall unsigned int perftest_thread(LPVOID void_arg)
#else
void* perftest_thread(void* void_arg)
#endif
{
struct thread_arg* arg = void_arg;
int (*lispfun)() = arg->funkyfun;
int ncalls = arg->n_calls;
int i;
for (i=0; i<ncalls; ++i) lispfun();
return 0;
}
int minimal_perftest(void* ptr, int n_calls)
{
struct thread_arg arg;
arg.funkyfun = ptr;
arg.n_calls = n_calls;
#ifdef _WIN32
HANDLE thr;
thr = (HANDLE)_beginthreadex(NULL, 0, perftest_thread, &arg, 0, NULL);
WaitForSingleObject(thr,0xffffffff);
CloseHandle(thr);
#else
pthread_t thr;
pthread_create(&thr, 0, perftest_thread, &arg);
pthread_join(thr,0);
#endif
return 0;
}
#ifdef _WIN32
__stdcall unsigned int doThatThing(void* void_arg)
#else
void* doThatThing(void* void_arg)
#endif
@ -63,7 +96,7 @@ int call_thing_from_threads(void* ptr, int n_threads, int n_calls)
threads[i].arg.index = i + 1;
threads[i].arg.n_calls = n_calls;
#ifdef _WIN32
threads[i].handle = CreateThread(NULL, 0, doThatThing, &threads[i].arg, 0, NULL);
threads[i].handle = (HANDLE)_beginthreadex(NULL, 0, doThatThing, &threads[i].arg, 0, NULL);
#else
pthread_create(&threads[i].pthread_id, 0, doThatThing, &threads[i].arg);
#endif

View file

@ -38,6 +38,14 @@
:output t :error :output)
(sb-alien:load-shared-object solib)))
;;;; Just exercise a ton of calls from 1 thread
(sb-alien::define-alien-callback perftestcb int () 0)
(defun trivial-call-test (n)
(with-alien ((testfun (function int system-area-pointer int) :extern "minimal_perftest"))
(alien-funcall testfun (alien-sap perftestcb) n)))
(time (trivial-call-test 200000))
;;;;
(defglobal *counter* 0)
(declaim (fixnum *counter*))
(defglobal *ok* (list t))