Re: Process-resume hangs

Gary Byers <[email protected]> Mon, 9 Jan 2006 07:05:17 -0700 (MST)
Newsgroups gmane.lisp.openmcl.bugs
Message-ID <[email protected]>
(ccl:process-suspend ccl:*current-process*) can't work as implemented,
and I'm not sure if -should- work.  (If it's decided that it shouldn't,
it should probably detect that case and signal an error rather than
fouling things up as it currently does.)

The documentation claims that a process can suspend itself and be
resumed by another process; it also notes that PROCESS-SUSPEND can
be dangerous, since the suspended process may own a lock or other
resources, and this can (fairly easily) lead to deadlock.  It doesn't
note the fact that that act of suspending a process requires a lock,
and if a process suspends itself it continues to own this lock (that
was either not true when the documentation was first written, or
was simply overlooked.)

The functions that you traced (CCL::%SUSPEND-TCR and CCL::%RESUME-TCR)
just call these C functions:

Boolean
lisp_suspend_tcr(TCR *tcr)
{
   Boolean suspended;
   TCR *current = get_tcr(true);

   LOCK(lisp_global(TCR_LOCK),current);
   suspended = suspend_tcr(tcr);
   UNLOCK(lisp_global(TCR_LOCK),current);
   return suspended;
}

Boolean
lisp_resume_tcr(TCR *tcr)
{
   Boolean resumed;
   TCR *current = get_tcr(true);

   LOCK(lisp_global(TCR_LOCK),current);
   resumed = resume_tcr(tcr);
   UNLOCK(lisp_global(TCR_LOCK), current);
   return resumed;
}

So if the current thread suspends itself, it won't UNLOCK the TCR_LOCK
and anything waiting on the TCR_LOCK will wait forever.  (That
includes attempts to resume any suspended thread, or invoke the GC, or
a few other things.)

I'm tempted to say that the documentation should be changed and
that PROCESS-SUSPEND should detect attempts to suspend the current
process and refuse to do so.  Using a semaphore - as in:

(defvar *a-semaphore* (make-semaphore))

(let* ((proc (process-run-function "example"
                                    #'(lambda ()
                                        (format t "~& suspending test process")
                                        (wait-on-semaphore *a-semaphore*)
                                        (format t "~& resumed ~%")))))
   (sleep 5)  ; or whatever
   (signal-semaphore *a-semaphore*))

- is likely to be more robust for lots of reasons.





On Mon, 9 Jan 2006, Dan Corkill wrote:

> The following simple test hangs in the call to process-resume (running
> on "Version 1.0 (DarwinPPC32)"):
>
> (in-package :common-lisp-user)
>
> (defun simple-test ()
>   (let ((process
>          (ccl:process-run-function
>              "Test"
>            #'(lambda ()
>                (format t "~&;; Suspending test process...~%")
>                (finish-output)
>                (ccl:process-suspend ccl:*current-process*)
>                (format t "~&;; Resumed~%")
>                (finish-output)))))
>     (format t "~&;; Starting test...~%")
>     ;; Allow plenty of time for test process to start up and suspend:
>     (sleep 3)
>     (format t "~&;; Resuming test process...~%")
>     (finish-output)
>     (ccl:process-resume process)
>     (format t "~&;; Test completed.~%")))
>
> (progn (trace ccl::%suspend-tcr)
>        (trace ccl::%resume-tcr))
>
> (simple-test)
>
>
>
>
>
> _______________________________________________
> Bug-openmcl mailing list
> [email protected]
> http://clozure.com/mailman/listinfo/bug-openmcl
>
>