Re: trap to debugger when compiling from multiple threads

Gary Byers <[email protected]> Fri, 1 Aug 2003 22:26:01 -0600 (MDT)
Newsgroups gmane.lisp.openmcl.bugs
Message-ID <[email protected]>

On Fri, 1 Aug 2003, Eric Marsden wrote:

> Hi,
>
> Loading the following code into OpenMCL causes it to break into the
> debugger. I see the same behaviour on Darwin and LinuxPPC, with recent
> CVS builds.

Aside from the problem I noticed this morning, I think that there are
a few other issues.

First of all, there are several problems with PROCESS-RESET.  It's
(vaguely) noted in the documentation that PROCESS-RESET needs a lot
of work; one of the problems seems to be that a process can't
easily reset itself.  Calling (PROCESS-RESET *CURRENT-PROCESS*)
currently has no effect, so the thread pushes itself on to the
pool, signals the semaphore, and then exits (because its initial
function has returned.)  If a thread exits like this, it should
clearly tell the lisp that there's no longer a pthread associated
with the lisp process (the crash you reported when PROCESS-PRESET
tries to use that defunct pthread.)

It's probably about time to fix that; doing so will expose another
problem:

>
> ;; run BODY inside a new thread
> #+openmcl-native-threads
> (defmacro with-spawned-thread (&body body)
>   `(let ((thread nil))
>      (ccl:wait-on-semaphore *thread-pool-semaphore*)
>      (ccl:with-lock-grabbed (*thread-pool-lock*)
>         (setq thread (pop *thread-pool*)))
>      (format *debug-io* "Acquired process ~A~%" thread)
>      (assert (ccl::processp thread))
>      (ccl:process-preset thread
>        (lambda ()
>          ,@body
>          (ccl:process-reset ccl:*current-process*)

Once a thread has reset itself, it'll be in a disabled state.  It
won't be able to grab the lock, add itself to the pool, and signal the
semaphore.  (Among other reasons, PROCESS-RESET has effectively done a
THROW, so the subsequent code is unreachable.)

>          (ccl:with-lock-grabbed (*thread-pool-lock*)
>             (push ccl:*current-process* *thread-pool*)
>             (ccl:signal-semaphore *thread-pool-semaphore*))))

If (PROCESS-RESET *CURRENT-PROCESS*) worked, we'd pretty much want it
to happen -after- we've pushed ourselves back on the pool, signaled the
semaphore, and released the lock; at that point, we'd want to enter
an idle state where we're waiting to be preset again or killed.

As soon as we release the lock, the calling thread will be able to
pop us off of the pool and will start trying to preset us and enable
us again; this may happen before, during, or after our attempt to
reset ourselves.  I -think- that this can be made to work reliably,
but need to check that.