Martin wrote 11 lines
On 04/02/2018 20:23, Sven Barth via fpc-devel wrote:
>
> Would you please test whether my change in r38115 (applied to 3.0.2)
> makes any difference? Calling RemoveQueuedEvents() with a thread, but no
> method (which happens during a thread's destruction) was up to then a
> way to corrupt the queue. (Well, it could still corrupt the queue if a
> thread instance is freed while its blocked inside a Synchronize call,
> but that is asking for a whole different sort of trouble anyway)
>
Thanks.
I will apply the patch. And wait if the error still happens.
Well, I am back faster than I thought, applied the patch, rebuild the IDE, and it still happened.
Well this time I was able to get it while the IDE was already running. But exact same stack.
I used a breakpoint on ThreadQueueAppend to see what threads are involved ( I figure, this must be called, for the error to happen)
During startup, the only threads I could detect, are online-package-manager. This is new, and I havent had it installed for long, so quite possible (given that I havent seen the crash until recently).
The other location, was in a thread running the compiler, when the IDE compiles a project. This code been there for longer.
-----------------
In the online package manager, as far as I was able to get by now, it is possible that an exception occurred somewhere.
I can't get it to happen in the debugger, probably because the debugger changes timings.
I have been able to force an error in the opm, and get a different error in checkSyncronize. (30% chance in the debugger)
Maybe it is the same, just a diff timing.... If the debugger had not interfered, collecting info, then maybe the destroy would have been a tick later, in PopThreadQueueHead
Dont know for sure.....
Also, even if the below is related, this may not explain the error while compiling.
When I cause an exception inside the sub-thread, then in the main thread, I get
procedure ExecuteThreadQueueEntry(aEntry: TThread.PThreadQueueEntry); begin
if Assigned(aEntry^.Method) then
aEntry^.Method() /// aentry points to F0F0F0F0
But the important thing here is, the sub thread that send the event is in REMOVE_FREED_FIXED_CHUNKS called from its destroy.
So yes it seem the thread gets destroyed, while the event is still in the queue.
-----------------------
To go more into detail. Though I havent yet fully figured it.....
There are actually 4 threads (thread id)
- main (1)
- threadtimer (this will create the 2 other threads) (2)
- threadtimer for timeout (3)
- opm thread (4)
the below order of events is established by breakpoints that where hit during debugging
timout -> ThreadQueueAppend
opm -> ThreadQueueAppend
main -> checksynchronize
... PopThreadQueueHead (before the "while" in CheckSynchronize // new call to CheckSynchronize)
... an exception occured inside the event (this should be the event of the timeout timer)
... PopThreadQueueHead (inside/end of "while" in CheckSynchronize // still SAME call to CheckSynchronize) opm -> leaves it DoExecute loop // but if I am right, its event has not yet been executed...
Now it is getting weird (probably because opm is already freeing mem main has 3 further calls to PopThreadQueueHead -> ALL (inside/end of "while" in CheckSynchronize // still SAME call to CheckSynchronize) The while loop should have exited, there are no matching ThreadQueueAppend (I do not have a stacktrace for opm2 at this time....)
After that the crash happens. (opm2 is inside its destroy)
---------
I have no idea why or how the opm thread leaves it DoExecute, while it should still wait for its synchronize to finish.
The timout thread would probably have finished, since I did not find a try except around the synchronize in it.