<div>Hello Juan Jose.</div><div> </div><div>It's enough to have a fix for the old libc only.</div><div> </div><div>It's a good idea, thanks. I will only need to think about race conditions, like if GC starts after the sigwait returns, but before we called</div><div>GC_register_my_thread. Or this code doesn't allocate any heap memory and should not be protected by GC?</div><div> </div><div>Best regards,</div><div>- Anton</div><div> </div><div> </div><div>20.01.2011, 00:16, "Juan Jose Garcia-Ripoll" <juanjose.garciaripoll@googlemail.com>:</div><blockquote>I only have one suggestion, which is to temporarily deregister that thread so that the garbage collector does not suspend it. Something like<br /><br /><br />        /* Waiting may fail! */<br />        int status;<br />        GC_unregister_my_thread();<br />         status = sigwait(&handled_set, &signo);<br />        if (status == 0) {<br />            if (interrupt_signal == signo)<br />                goto RETURN;<br />            signal_code = call_handler(lisp_signal_handler, signo,<br />                            NULL, NULL);<br />            if (!Null(signal_code)) {<br />                mp_process_run_function(3, @'si::handle-signal',<br />                            @'si::handle-signal',<br />                             signal_code);<br />            }<br />        }<br />        GC_register_my_thread((void*)&status);<br /><br />Unfortunately this can not be used when the library works as expected (sigwait does not block all signals) because some interrupt handlers may need the garbage collector to work.<br /> <br />Juanjo<br /><br /><div class="gmail_quote">On Wed, Jan 19, 2011 at 7:21 PM, Anton Vodonosov <span dir="ltr"><<a href="mailto:avodonosov@yandex.ru">avodonosov@yandex.ru</a>></span> wrote:<br /><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid #cccccc; padding-left: 1ex;">Hello.<br /> <br /> I am building ECL for glibc-2.2.5. With that old glibc version<br /> a deadlock occurs any time when garbage collection starts.<br /> <br /> I found out the mechanics of how it happens.<br /> <br /> Not sure if you want to fix it, because the libc version is old,<br /> but maybe you can provide an advice how can I workaround it.<br /> <br /> How it happens. Two parts are involved:<br /> <br /> 1. The Boehm-Weiser GC tries to stop all the threads before<br />   performing garbage collection (it's called "stop world").<br />   This is implemented by sending a SIG_SUSPEND signal to<br />   every thread. The signal handler in every thread then<br />   tells "ok, I am stopped" to the thread which wants to perform<br />   the garbage collection, and then waits until the GC instruct<br />   it to restart.<br /> <br />   The "I am stopped" confirmation is sent via a<br />   semaphore: sem_post(&GC_suspend_ack_sem).<br /> <br />   The GC expects this from every thread. It performs<br />   sem_wait(&GC_suspend_ack_sem) as many times, as<br />   many threads were notified by the SIG_SUSPEND signal.<br /> <br />   The corresponding code is in the src/gc/pthread_stop_world.c,<br />   the functions GC_stop_world which calls GC_suspend_all.<br />   The signal handler behavior is implemented in the<br />   GC_suspend_handler_inner.<br /> <br /> 2. ECL has a special thread which handles all the signals<br />   not handled by other threads.<br /> <br />   See it's implementation in the function<br />   asynchronous_signal_servicing_thread, file src/c/unixint.d.<br /> <br />   It is an endless loop of<br />      sigwait(<signlals blocked in other threads>);<br /> <br /> The deadlock is caused by the difference in sigwait behavior<br /> between the old libc and the contemporary libc.<br /> <br /> Namely, what happens when the asynchronous_signal_servicing_thread<br /> is waiting in sigwait(<signlals blocked in other threads>),<br /> and some signal _not_ from this set arrive? In particular, when<br /> GC sends the SIG_SUSPEND signal.<br /> <br /> The contemporary libc calls the signal handler. The old libc<br /> doesn't call the signal handler; sigwait just blocks<br /> the signlas other than it waits for.<br /> <br /> In result, with the old libc the sem_wait(&GC_suspend_ack_sem)<br /> is  not performed by the asynchronous_signal_servicing_thread,<br /> therefore the GC waits on the semaphore forever.<br /> <br /> ECL hangs first time the GC is invoked, for example on<br /> (MAKE-ARRAY <span class="wmi-callto">3000000</span>).<br /> <br /> What would be the easiest way to workaround this problem?<br /> <br /> Best regards,<br /> - Anton<br /> <br /> <br /> <br /> <br /> <br /> ------------------------------------------------------------------------------<br /> Protect Your Site and Customers from Malware Attacks<br /> Learn about various malware tactics and how to avoid them. Understand<br /> malware threats, the impact they can have on your business, and how you<br /> can protect your company and customers by using code signing.<br /> <a href="http://p.sf.net/sfu/oracle-sfdevnl" target="_blank">http://p.sf.net/sfu/oracle-sfdevnl</a><br /> _______________________________________________<br /> Ecls-list mailing list<br /> <a href="mailto:Ecls-list@lists.sourceforge.net">Ecls-list@lists.sourceforge.net</a><br /> <a href="https://lists.sourceforge.net/lists/listinfo/ecls-list" target="_blank">https://lists.sourceforge.net/lists/listinfo/ecls-list</a><br /></blockquote></div><br /><br /><br />-- <br />Instituto de Física Fundamental, CSIC<br />c/ Serrano, 113b, Madrid 28006 (Spain) <br /><a href="http://juanjose.garciaripoll.googlepages.com" target="_blank">http://juanjose.garciaripoll.googlepages.com</a><br /></blockquote>