|
From: Daniel J S. <dan...@ie...> - 2014-11-16 09:24:04
|
On 11/16/2014 01:31 AM, Daniel J Sebald wrote:
> On 11/15/2014 10:09 PM, sfeam wrote:
>> On Saturday, 15 November 2014 08:32:38 PM Daniel J Sebald wrote:
>>
>>> I meant "zombie", not daemon.
>>
>> I don't see a zombie. The original process really does exit.
>>
>>> There must be some way of doing this without having to stop/restart a
>>
>>> thread in the process.
>>
>> The problem does not depend stop/start of a thread.
>>
>> It acts the same even if gnuplot is built in single-threaded mode.
>>
>> The exit+persist procedure is to fork(), leaving a parent and a child.
>>
>> The parent calls atexit() and exits. The child is supposed
>>
>> to maintain the plot window. Both the parent and child can
>>
>> be a single thread. I don't say that this is necessarily the
>>
>> only possible procedure or the best procedure, but that's the
>>
>> way it currently works.
>
> The fork idea is OK. (Well, so-so. Remember there's the limitation of
> WXT not being an outboard driver.)
>
> I'm wondering about this hunk of code though:
>
> /* (re)start gui loop */
> wxTheApp->OnRun();
>
> If I'm understanding correctly, there is some sort of custom event
> handling whereby gnuplot manages input events and then shuffles them off
> to wxWidgets with the ::SendEvent( wxEvent&event) function. I.e.,
>
> /* wrapper for AddPendingEvent or ProcessEvent */
> void wxtApp::SendEvent( wxEvent&event)
> {
> #ifdef WXT_MULTITHREADED
> AddPendingEvent(event);
> #else /* !WXT_MULTITHREADED */
> ProcessEvent(event);
> #endif /* !WXT_MULTITHREADED */
> }
>
> Generally, gnuplot is not using wxWidgets event loop (because otherwise
> it would be unable to do anything). But then, when gnuplot exits with
> persist, it passes event loop processing off to wxWidgets using
> wxTheApp->OnRun().
OK, I was mistaken on that. There's another ->OnRun() in the code.
This one as part of wxtThread::Entry():
/* gui loop */
wxTheApp->OnRun();
/* Workaround for a deadlock when the main thread will Wait() for this one.
* This issue comes from the fact that our gui main loop is not in the
* main thread as wxWidgets was written for. */
wxt_MutexGuiLeave();
Maybe that's where the problem is. The wxt_MutexGuiLeave() routine
looks like:
void wxt_MutexGuiLeave()
{
FPRINTF2((stderr,"unlocking gui mutex\n"));
#ifdef WXT_MULTITHREADED
if (!wxt_handling_persist)
wxMutexGuiLeave();
#endif /* WXT_MULTITHREADED */
}
I think the idea is that if the window is persistent and exiting, then
do not leave go of the Mutex, i.e., GUI access from non-main-thread.
However, I've just done some fprintf's on my system to find that this
may not happen in the right order. The "wxt_handling_persist" variable
is set to "true" inside wxt_atexit(). However, what I'm seeing is that
/* gui loop */
wxTheApp->OnRun();
inside wxtThread::Entry() [repeat the one inside wxtThread::Entry()]
completes prior to wxt_atexit() call. So "wxt_handling_persist" isn't
set when OnRun() initially exits. I'm guessing that is what the
original intent of this variable was, otherwise it doesn't seem to have
any purpose inside of wxt_atexit().
That does seem like it could be an issue here, i.e., the persistent WXT
terminal window is trying to access widgets for which it doesn't have a
lock on the GUI resources.
Dan
|