Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / lazarus / 2013-03

Tracking down an intermittent termination exception

7 messages · 4 people ·

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Mark Morgan Lloyd

I've got a program here with main and background thread, it doesn't do anything fancy like explicitly hooking the event loop. Intermittently it displays something like this during termination:

An unhandled exception occurred at $08080639 :
EInOutError :
$08080639 CDONECRITICALSECTION, line 503 of ../unix/cthreads.pp $08075B84 DONECRITICALSECTION, line 199 of
/usr/local/src/fpc/fpcbuild-2.6.2/fpcsrc/rtl/inc/thread.inc $080D5404 COMMONCLEANUP, line 1751 of
/usr/local/src/fpc/fpcbuild-2.6.2/fpcsrc/rtl/objpas/classes/classe s.inc
$080DD8A8 CLASSES_finalize, line 51 of ../unix/classes.pp $08072DAF FINALIZEUNITS, line 833 of
/usr/local/src/fpc/fpcbuild-2.6.2/fpcsrc/rtl/inc/system.inc $08072F28 INTERNALEXIT, line 886 of
/usr/local/src/fpc/fpcbuild-2.6.2/fpcsrc/rtl/inc/system.inc $08073038 DO_EXIT, line 937 of
/usr/local/src/fpc/fpcbuild-2.6.2/fpcsrc/rtl/inc/system.inc $0805E44B main, line 69 of BorgUM.lpr
$B6E57CA6

, I see that the affected line is

   DoneCriticalSection(SynchronizeCritSect);

Assuming that this is a problem in my own code, what sort of thing should I be looking for?

Laz+LCL 1.1, FPC 2.6.2, Linux x86. This might in practice happen most often when X is tunneled over ssh: could this mess up LCL termination?

Mark Morgan Lloyd markMLl .AT. telemetry.co .DOT. uk [Opinions above are the author's, not those of his employers or colleagues]
Mattias Gaertner
to Mark Morgan Lloyd
Show quoted text 28 lines
I've got a program here with main and background thread, it doesn't do anything fancy like explicitly hooking the event loop. Intermittently it displays something like this during termination: An unhandled exception occurred at $08080639 : EInOutError : $08080639 CDONECRITICALSECTION, line 503 of ../unix/cthreads.pp $08075B84 DONECRITICALSECTION, line 199 of /usr/local/src/fpc/fpcbuild-2.6.2/fpcsrc/rtl/inc/thread.inc $080D5404 COMMONCLEANUP, line 1751 of /usr/local/src/fpc/fpcbuild-2.6.2/fpcsrc/rtl/objpas/classes/classe s.inc $080DD8A8 CLASSES_finalize, line 51 of ../unix/classes.pp $08072DAF FINALIZEUNITS, line 833 of /usr/local/src/fpc/fpcbuild-2.6.2/fpcsrc/rtl/inc/system.inc $08072F28 INTERNALEXIT, line 886 of /usr/local/src/fpc/fpcbuild-2.6.2/fpcsrc/rtl/inc/system.inc $08073038 DO_EXIT, line 937 of /usr/local/src/fpc/fpcbuild-2.6.2/fpcsrc/rtl/inc/system.inc $0805E44B main, line 69 of BorgUM.lpr $B6E57CA6 , I see that the affected line is DoneCriticalSection(SynchronizeCritSect); Assuming that this is a problem in my own code, what sort of thing should I be looking for?

Double call of DoneCriticalSection, missing InitCriticalSection, heap corruption.

Laz+LCL 1.1, FPC 2.6.2, Linux x86. This might in practice happen most often when X is tunneled over ssh: could this mess up LCL termination?

As far as I know: no

Mattias

Mark Morgan Lloyd
to Mattias Gaertner
Mattias Gaertner wrote 9 lines
> , I see that the affected line is > > DoneCriticalSection(SynchronizeCritSect); > > Assuming that this is a problem in my own code, what sort of thing > should I be looking for? Double call of DoneCriticalSection, missing InitCriticalSection, heap corruption.

So does that imply that I'm doing something careless like nesting a Synchronize() or calling it from the main thread?

> Laz+LCL 1.1, FPC 2.6.2, Linux x86. This might in practice happen most > often when X is tunneled over ssh: could this mess up LCL termination? As far as I know: no

Thanks for that, I'll keep my eyes open.

Mark Morgan Lloyd markMLl .AT. telemetry.co .DOT. uk [Opinions above are the author's, not those of his employers or colleagues]
Sven Barth
to Mark Morgan Lloyd: I've got a program here with main and background thread, it doesn't do anything fancy…
Mark Morgan Lloyd wrote 28 lines
I've got a program here with main and background thread, it doesn't do anything fancy like explicitly hooking the event loop. Intermittently it displays something like this during termination: An unhandled exception occurred at $08080639 : EInOutError : $08080639 CDONECRITICALSECTION, line 503 of ../unix/cthreads.pp $08075B84 DONECRITICALSECTION, line 199 of /usr/local/src/fpc/fpcbuild-2.6.2/fpcsrc/rtl/inc/thread.inc $080D5404 COMMONCLEANUP, line 1751 of /usr/local/src/fpc/fpcbuild-2.6.2/fpcsrc/rtl/objpas/classes/classe s.inc $080DD8A8 CLASSES_finalize, line 51 of ../unix/classes.pp $08072DAF FINALIZEUNITS, line 833 of /usr/local/src/fpc/fpcbuild-2.6.2/fpcsrc/rtl/inc/system.inc $08072F28 INTERNALEXIT, line 886 of /usr/local/src/fpc/fpcbuild-2.6.2/fpcsrc/rtl/inc/system.inc $08073038 DO_EXIT, line 937 of /usr/local/src/fpc/fpcbuild-2.6.2/fpcsrc/rtl/inc/system.inc $0805E44B main, line 69 of BorgUM.lpr $B6E57CA6 , I see that the affected line is DoneCriticalSection(SynchronizeCritSect); Assuming that this is a problem in my own code, what sort of thing should I be looking for?

After looking through the following things:

- code of CDoneCriticalSection (in rtl/unix/cthreads.pp)
- man page of pthread_mutex_destroy
- code of fpc_threaderror (in rtl/inc/system.inc)
- code of RunErrorToExcept (in rtl/objpas/sysutils/sysutils.inc)

the most valid assumption is that the critical section is destroyed while it's in use. As this critical section is only used inside a Synchronize call from a thread (the mainthread will directly call the method without any locking) it seems that your background thread is inside a Synchronize call when you terminate your application.

Solution: Tell the thread to terminate (if you use the thread's Terminate property you'll need to check this inside your thread's loop) and then wait for (TThread.WaitFor) it to finish before you continue with termination. This will also ensure that any cleanup that is done inside the thread is finished before the RTL is finalized.

Regards,
Sven

Mark Morgan Lloyd
to Sven Barth
Sven Barth wrote 17 lines
> DoneCriticalSection(SynchronizeCritSect); > > Assuming that this is a problem in my own code, what sort of thing > should I be looking for? After looking through the following things: - code of CDoneCriticalSection (in rtl/unix/cthreads.pp) - man page of pthread_mutex_destroy - code of fpc_threaderror (in rtl/inc/system.inc) - code of RunErrorToExcept (in rtl/objpas/sysutils/sysutils.inc) the most valid assumption is that the critical section is destroyed while it's in use. As this critical section is only used inside a Synchronize call from a thread (the mainthread will directly call the method without any locking) it seems that your background thread is inside a Synchronize call when you terminate your application.

Synchronize() is only used for message display, the program's silent until it sees TCP traffic. From what you're saying I suspect that it's probably caused by the socket the thread's waiting on being forcibly closed, at which point the thread tries to display a message.

Show quoted text 5 lines
Solution: Tell the thread to terminate (if you use the thread's Terminate property you'll need to check this inside your thread's loop) and then wait for (TThread.WaitFor) it to finish before you continue with termination. This will also ensure that any cleanup that is done inside the thread is finished before the RTL is finalized.

Thanks Sven, I'll dig. At present the background thread is watching for the main thread to start terminating as a stimulus for it to fall through the main loop, is there a wiki page or an example somewhere showing "best practice" for this sort of thing?

Mark Morgan Lloyd markMLl .AT. telemetry.co .DOT. uk [Opinions above are the author's, not those of his employers or colleagues]
Sven Barth
to Mark Morgan Lloyd

Am 26.03.2013 12:16 schrieb "Mark Morgan Lloyd" <

Show quoted text 7 lines
: Sven Barth wrote: >> DoneCriticalSection(SynchronizeCritSect); >> >> Assuming that this is a problem in my own code, what sort of thing

should I be looking for?

Show quoted text 10 lines
> > > After looking through the following things: > > - code of CDoneCriticalSection (in rtl/unix/cthreads.pp) > - man page of pthread_mutex_destroy > - code of fpc_threaderror (in rtl/inc/system.inc) > - code of RunErrorToExcept (in rtl/objpas/sysutils/sysutils.inc) > > the most valid assumption is that the critical section is destroyed

while it's in use. As this critical section is only used inside a Synchronize call from a thread (the mainthread will directly call the method without any locking) it seems that your background thread is inside a Synchronize call when you terminate your application.

Synchronize() is only used for message display, the program's silent

until it sees TCP traffic. From what you're saying I suspect that it's probably caused by the socket the thread's waiting on being forcibly closed, at which point the thread tries to display a message.

Yes, that could he the problem then.

> Solution: Tell the thread to terminate (if you use the thread's

Terminate property you'll need to check this inside your thread's loop) and then wait for (TThread.WaitFor) it to finish before you continue with termination. This will also ensure that any cleanup that is done inside the thread is finished before the RTL is finalized.

Thanks Sven, I'll dig. At present the background thread is watching for

the main thread to start terminating as a stimulus for it to fall through the main loop, is there a wiki page or an example somewhere showing "best practice" for this sort of thing?

I don't know whether there is something like that... :(

Regards,
Sven
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lazarus.freepascal.org/pipermail/lazarus/attachments/20130326/3891caae/attachment.html>

Luca Olivetti
to Sven Barth: After looking through the following things: - code of CDoneCriticalSection (in…

Al 26/03/13 11:46, En/na Sven Barth ha escrit:

Solution: Tell the thread to terminate (if you use the thread's Terminate property you'll need to check this inside your thread's loop) and then wait for (TThread.WaitFor) it to finish before you continue with termination.

Calling WaitFor on a thread that could be in a Synchronize call was a no-no in delphi (and AFAIK even in Lazarus) since it could produce a deadlock.
That's not the case anymore?
Because of that I always use a workaround: I set a boolean at the end of the thread and, in the main thread, when I want to terminate the thread, after calling Terminate I loop on a CheckSynchronize call waiting for that boolean to become true.

Bye

Luca Olivetti Wetron Automation Technology http://www.wetron.es Tel. +34 935883004 Fax +34 935883007