guile-user
[Top][All Lists]
Advanced

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

Re: guile 2.0.9 build on mingw


From: Eli Zaretskii
Subject: Re: guile 2.0.9 build on mingw
Date: Wed, 12 Jun 2013 20:46:07 +0300

> From: address@hidden (Ludovic Courtès)
> Cc: Mark H Weaver <address@hidden>,  address@hidden
> Date: Wed, 12 Jun 2013 00:11:46 +0200
> 
> > What eventually did the trick was configuring --with-threads=no.  Once
> > I did that, the build ran successfully and almost 100% cleanly to
> > completion.  (I will report the details about "almost" later.)
> >
> > I will try to compare the two builds and find what breaks the one with
> > threads.  Since my knowledge about pthreads in general and on Windows
> > in particular is strictly zero, I'm not sure I'll know where to look.
> > So perhaps the following observation will help someone here to come up
> > with ideas or hints about where to look: Guile gets stuck when it is
> > about to exit.  That is, it processes its input completely (e.g.,
> > compiles the .scm file), writes out the corresponding output (e.g.,
> > the .go file), announces that the output was written, and then gets
> > stuck.  So this suggests something related to some bookkeeping done at
> > exit; any ideas what that could be?
> 
> The backtrace you reported before suggests that it’s stuck waiting for a
> signal delivery thread mutex, right?  I have no idea how this would
> happen, though.

I looked deeper into this.  What I saw surprised me, but maybe that's
because I know nothing about pthreads, nor how Guile uses them.  I
will describe my findings in the hope that someone here will know
more.  In a nutshell, I think the hang waiting for a mutex is a
symptom, not the problem; see below.

What I did was stop Guile at the entry to 'main', and then attach GDB
and set a breakpoint at scm_i_ensure_signal_delivery_thread, before
letting Guile proceed.  I expected that function to be called some
time during the startup, and I expected to see GDB announce a new
thread.  Surprisingly, none of that happened.  Instead, the function
is called when Guile is done (it was compiling a .scm file), and is
exiting!  See the backtrace below; you can clearly see that the
top-level call-stack frame is in ExitProcess, and the whole sequence
of calls leading to the attempt to create a signal delivery thread
starts in on_thread_exit.

What happens next is that the attempt to launch that thread fails
here:

     SCM
     scm_spawn_thread (scm_t_catch_body body, void *body_data,
                       scm_t_catch_handler handler, void *handler_data)
     {
       spawn_data data;
       scm_i_pthread_t id;
       int err;

       data.parent = scm_current_dynamic_state ();
       data.body = body;
       data.body_data = body_data;
       data.handler = handler;
       data.handler_data = handler_data;
       data.thread = SCM_BOOL_F;
       scm_i_pthread_mutex_init (&data.mutex, NULL);
       scm_i_pthread_cond_init (&data.cond, NULL);

       scm_i_scm_pthread_mutex_lock (&data.mutex);
       err = scm_i_pthread_create (&id, NULL, spawn_thread, &data); <<<<<<<
       if (err)
         {
           scm_i_pthread_mutex_unlock (&data.mutex);
           errno = err;
           scm_syserror (NULL);
         }

scm_i_pthread_create returns err = 11 (EAGAIN), and then Guile calls
scm_syserror.  I believe that call outputs the Scheme backtrace, and
then Guile hangs as I described.

The call to start the signal delivery thread comes from here:

     /* Perform thread tear-down, in guile mode.
      */
     static void *
     do_thread_exit (void *v)
     {
       scm_i_thread *t = (scm_i_thread *) v;

       /* Ensure the signal handling thread has been launched, because we might 
be
          shutting it down.  This needs to be done in Guile mode.  */
       scm_i_ensure_signal_delivery_thread ();  <<<<<<<<<<<<<<<<<<<<<

Why isn't the signal delivery thread launched at program start, and
why is it launched at exit?

Also, is it possible for you or someone else to describe how the
signal delivery stuff is supposed to work, especially since there are
some MinGW related comments in scmsigs.c that mention signals between
processes (how's that related? Guile is a single process, right?)?
I'd like to understand a bit more what is going on here.

> > Another set of disabled features is the network related functions --
> > for some reason, the build process insists on h_errno being available,
> > although h_errno is an obsolete facility that AFAIK no one is treating
> > seriously anymore.  Why not use errno instead?
> 
> I don’t know.  It’s used only in net_db.c, and only if ‘h_errno’ is
> available.
> 
> Is there any harm in using it when it’s available?

No, of course not.  The harm is to disable all network features when
h_errno is _not_ available.

> Could it be that older-but-not-too-old MinGW versions required use of
> ‘h_errno’?

I sincerely doubt that.  Windows doesn't have h_errno, and AFAIK never
had.

Here's the backtrace when scm_spawn_thread is called during exit:

     Breakpoint 1, scm_spawn_thread (
         address@hidden <signal_delivery_thread>,
         address@hidden, handler=0x4317a4 <scm_handle_by_message>,
         address@hidden <scm_i_open_file__name_string_stringbuf+20>) at 
threads.c:1119
     1119    {
     (gdb) bt
     #0  scm_spawn_thread (address@hidden <signal_delivery_thread>,
         address@hidden, handler=0x4317a4 <scm_handle_by_message>,
         address@hidden <scm_i_open_file__name_string_stringbuf+20>) at 
threads.c:1119
     #1  0x00436328 in start_signal_delivery_thread () at scmsigs.c:200
     #2  0x6248b751 in pthread_once () from d:\usr\bin\pthreadGC2.dll
     #3  0x0043642c in scm_i_ensure_signal_delivery_thread () at scmsigs.c:212
     #4  0x00432c10 in do_thread_exit (v=0x9b0f00) at threads.c:671
     #5  0x0045f8bc in c_body (d=0x28f6a0) at continuations.c:511
     #6  0x00454b9b in vm_regular_engine (vm=0xb95c80, program=0x0,
         argv=0x23f00a4, nargs=5121210) at vm-i-system.c:855
     #7  0x00414608 in scm_call_4 (proc=0x926b28, address@hidden,
         address@hidden, address@hidden,
         address@hidden) at eval.c:507
     #8  0x004312b2 in scm_catch_with_pre_unwind_handler (key=0x404,
         thunk=0x5408d80, handler=0x5408d70, pre_unwind_handler=0x5408d60)
         at throw.c:86
     #9  0x0043144e in scm_c_catch (address@hidden, body=0x5408d80,
         address@hidden <c_body>, body_data=0x5408d70,
         address@hidden, handler=0x5408d60,
         address@hidden <c_handler>,
         address@hidden,
         address@hidden <pre_unwind_handler>, address@hidden) at throw.c:213
     #10 0x0045ff4b in scm_i_with_continuation_barrier (
         address@hidden <c_body>, address@hidden,
         address@hidden <c_handler>,
         address@hidden,
         address@hidden <pre_unwind_handler>, pre_unwind_handler_data=0xb95c40) 
at continuations.c:449
     #11 0x0045ffdc in scm_c_with_continuation_barrier (
         func=0x432c00 <do_thread_exit>, data=0x9b0f00) at continuations.c:545
     #12 0x00431e04 in with_guile_trampoline (data=0x28f790) at threads.c:890
     #13 0x709cffa0 in ?? () from d:\usr\bin\libgc-1.dll
     #14 0x004326ec in with_gc_active (data=0x28f790,
         func=0x431dec <with_guile_trampoline>) at threads.c:238
     #15 with_guile_and_parent (base=0x28f768, data=0x28f790) at threads.c:936
     #16 0x709cae6f in ?? () from d:\usr\bin\libgc-1.dll
     #17 0x004328f0 in scm_i_with_guile_and_parent (parent=<optimized out>,
         data=0x9b0f00, func=0x432c00 <do_thread_exit>) at threads.c:951
     #18 scm_with_guile (func=0x432c00 <do_thread_exit>, data=0x9b0f00)
         at threads.c:957
     #19 0x709cae6f in ?? () from d:\usr\bin\libgc-1.dll
     #20 0x00431e76 in on_thread_exit (v=0x9b0f00) at threads.c:754
     #21 0x62481f14 in ptw32_callUserDestroyRoutines ()
        from d:\usr\bin\pthreadGC2.dll
     #22 0x624855a1 in pthread_win32_thread_detach_np ()
        from d:\usr\bin\pthreadGC2.dll
     #23 0x62485a45 in address@hidden () from d:\usr\bin\pthreadGC2.dll
     #24 0x624810ed in address@hidden () from d:\usr\bin\pthreadGC2.dll
     #25 0x77c69950 in ntdll!RtlQueryEnvironmentVariable ()
        from C:\Windows\SysWOW64\ntdll.dll
     #26 0x62480000 in ?? ()
     #27 0x77c7d6b2 in ntdll!LdrShutdownProcess ()
        from C:\Windows\SysWOW64\ntdll.dll
     #28 0x624810c0 in __dll_exit () from d:\usr\bin\pthreadGC2.dll
     #29 0x77c7d554 in ntdll!RtlExitUserProcess ()
        from C:\Windows\SysWOW64\ntdll.dll
     #30 0x75e97a0d in KERNEL32!ExitProcess ()
        from C:\Windows\syswow64\kernel32.dll




reply via email to

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