guile-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Cygwin port of Guile 2.2


From: Derek Upham
Subject: Re: Cygwin port of Guile 2.2
Date: Mon, 01 May 2017 13:48:13 -0700
User-agent: mu4e 0.9.17; emacs 25.1.1

Derek Upham <address@hidden> writes:
>> I think also that if you are most interested in a system in which
>> primitive-fork plays a large role, then probably you want a Guile
>> without threads (including the GC mark threads).  Threads + fork is not
>> a recipe for success :)
>
> Understood.  However, saying “primitive-fork requires a separate,
> threadless Guile installation” would be very limiting.  I’d like to be
> in a position where Guile will manage any threads that it creates
> under the hood; then it’s up to the program owner to guarantee that
> there are no other threads running at fork time.  Right now the
> under-the-hood threads appear to be:
>
> 1. The finalizer thread.
> 2. The signal delivery thread.
>
> (If you can think of any others, let me know.)
>
> For SCSH-style process forms, this comes up when trying to implement
> SCSH’s “early” child process auto-reap mechanism (section 3.4.1 in the
> SCSH manual).  The “early” policy works by setting up a handler for
> SIGCHLD.  We are guaranteed to have the signal delivery thread in that
> situation.  (The “late” policy hooks into the garbage collector, so it
> avoids this problem; it can have pathological edge cases for
> long-running programs, however.)

It turns out that, in the current Guile implementation, the thread cleanup code 
has inherent race conditions.  Running pthread_join() on a thread only 
guarantees that the thread has returned an exit value.  It doesn’t say anything 
about whether the thread has finally terminnated (which for Guile means running 
the thread-local variable cleanup using on_thread_exit()).  If there is a delay 
in running the thread-local variable cleanup (which happens occasionally), we 
end up forking a child that doesn’t run the thread-local variable cleanup.  In 
that case, the child process never updates the global list of threads and 
doesn’t unregister the thread from the garbage collector.

In these sorts of situations, the standard operating procedure is to extract 
most of the on_thread_exit() code into its own function, which the parent can 
call synchronously before the fork.  For safety when doing explicit cleanup, we 
would:

- Use the thread admin mutex to provide cross-thread protection.
- Use the thread struct “exited” field to prevent double-freeing.

(To make things more interesting, on_thread_exit() can end up shutting down the 
signal delivery thread.  We will have to handle or avoid a recursive mutex 
lock.)

However, the on_thread_exit() function has the comment

  /* This handler is executed in non-guile mode. */

at the top.  Can someone explain what that means and what the implications are? 
 How can I safely invoke the contained code from other contexts?

GDB also shows that Guile is spawning two threads at startup, and those don’t 
show up in the list of threads known to the system.

Thanks,

Derek

-- 
Derek Upham
address@hidden



reply via email to

[Prev in Thread] Current Thread [Next in Thread]