Recent

Author Topic: "exception class 'External :?'."  (Read 9377 times)

BIANCO

  • New member
  • *
  • Posts: 9
  • O Rio!? o Rio é um mundo cara!
"exception class 'External :?'."
« on: February 12, 2018, 02:08:44 am »
I am having this problem while destroying a thread.

Project TesteCromis raised exception class 'External :?'.

Does anyone know how to solve it?
-----
I'm using a very cool cron lib from Iztok Kacin, which creates a thread for each task, I need to insert the tasks and destroy them in runtime but this error is happening.

Debugging I got to this point from the Cromis.Scheduler lib, line 1087
class TScheduledEvent

     {$ IFDEF FPC} RTLEventDestroy {$ ELSE} CloseHandle {$ ENDIF} (@ FTermEvent);
The error appears when you pass this line.

"exception class 'External :?'."

The test application is on google drive, please if there was any genius that can help me I appreciate it.

https://drive.google.com/file/d/1w4cIlvFW21uXEeOuiGO3JxSyGm13Lq8w/view?usp=sharing

* This code was initially for Delphi, but works on free Pascal except for this point.

From what I've researched, this is apparently a stdcal or cdecl problem, but I do not know where to change it.
« Last Edit: February 12, 2018, 02:21:24 am by BIANCO »

rvk

  • Hero Member
  • *****
  • Posts: 6110
Re: "exception class 'External :?'."
« Reply #1 on: February 12, 2018, 09:32:34 am »
I can't speak about the problem in Cromos... but I do see a very big problem with you calling Form1 elements within the threads without using Synchronize.

Not only in LoadCronTab and DisplayCronInfo of the main thread but also in the DoOnScheduleStop etc of the cron threads.

One rule... NEVER update a component from another form/thread in a thread without using TThread.Synchronize() or TThread.Queue() !!!

(Maybe that's also the problem with this code in the library but I'm not sure. First fix that.)
Try to take out all the Form1 updates and see if it works then without error.

BIANCO

  • New member
  • *
  • Posts: 9
  • O Rio!? o Rio é um mundo cara!
Re: "exception class 'External :?'."
« Reply #2 on: February 12, 2018, 02:20:58 pm »
Hi, rvk, thanks!

I made the fixes, first on the Main Thread to refresh the screen, but the error continued.

By checking the Threads of the Cromis lib, I have seen that it uses Synchronize () or Queue () depending on the value passed in "SignalType" to execute OnScheduleEvent.

To validate what you have suggested, I have commented the assignment of all the events [were just logs, but updated the screen, ok] minus the OnScheduleEvent that runs in Synchronize ().

Even so, the error continues.

Once again, thank you! but if you have more tips just talk.

If it helps I'm sending the debug screen.

engkin

  • Hero Member
  • *****
  • Posts: 3112
Re: "exception class 'External :?'."
« Reply #3 on: February 12, 2018, 03:19:02 pm »
In your code you have:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.Button3Click(Sender: TObject);
  2. begin
  3.   ThreadTeste                 := TTheThread.Create(True);
  4.   ThreadTeste.FreeOnTerminate := True;
  5.   ThreadTeste.Start;
  6. end;

If you set FreeOnTerminate := True then you should not touch the thread after starting it. Because the thread will free and destroy itself when it is done.

Button4Click is touching the thread.

More over:
Code: Pascal  [Select][+][-]
  1. procedure TTheThread.Execute;
  2. begin
  3.   try
  4.   repeat
  5.     LoadCronTab;
  6.     DisplayCronInfo;
  7.     Sleep(5000);
  8.   until Terminated;
  9.   finally
  10.     OnTerminate(self);
  11.   end;
  12.  
  13. end;
OnTerminate is usually called if assigned. You are double calling it here. AND you are not checking if it is assigned. (It is *not* assigned).

The logic that calls Execute (when you call start) calls OnTerminate if it is assigned. So you do not have to call it.
« Last Edit: February 12, 2018, 03:30:35 pm by engkin »

engkin

  • Hero Member
  • *****
  • Posts: 3112
Re: "exception class 'External :?'."
« Reply #4 on: February 12, 2018, 03:23:11 pm »
Code: Pascal  [Select][+][-]
  1. destructor TTheThread.Destroy;
  2. begin
  3.   if Assigned(FScheduleTaskList) then
  4.      FreeAndNil(FScheduleTaskList);
  5.  
  6.   if Assigned(FKnowTasks) then
  7.     FreeAndNil(FKnowTasks);
  8.  
  9.   Self.Terminate;
  10.   inherited Destroy;
  11. end;

That does not make sense. Destroy is called after the terminate ( or Terminated := True )

rvk

  • Hero Member
  • *****
  • Posts: 6110
Re: "exception class 'External :?'."
« Reply #5 on: February 12, 2018, 03:29:37 pm »
That does not make sense. Destroy is called after the terminate ( or Terminated := True )
Yep, these are all problems in unPrincipal.pas.

But I also see a big problem in Cromis.Scheduler.pas itself (and that's the one causing the RTLEvent call problem).
For instance, there is this in TScheduledEvent.Stop:
Code: Pascal  [Select][+][-]
  1. {$IFDEF FPC}RTLEventSetEvent{$ELSE}SetEvent{$ENDIF}(@FTermEvent);
Ok, so for FPC the RTLEvents are used.
But in TScheduledEvent.Run() there is this:
Code: Pascal  [Select][+][-]
  1. FTermEvent := {$IFDEF MSWINDOWS}CreateEvent(nil, False, False, nil){$ELSE} RTLEventCreate{$ENDIF};
Here, RTLEventCreate() is NOT used because FPC on Windows also has MSWINDOWS defined.

There are a lot of these inconsistencies in the Cromis.Scheduler.pas.
All the IFDEFs for WINDOWS, MSWINDOWS and FPC should be examined and fixed.

BIANCO, where did you get the source-code from?


Edit:
Here is another:
Code: Pascal  [Select][+][-]
  1. {$IFDEF MSWINDOWS}
  2.   Windows, Messages,Types,
  3. {$ELSE}
  4.   LMessages, LCLType, LCLIntf,
  5. {$ENDIF}
Why wouldn't this be defined as:
Code: Pascal  [Select][+][-]
  1. {$IFNDEF FPC}
  2.   Windows, Messages,Types,
  3. {$ELSE}
  4.   LMessages, LCLType, LCLIntf,
  5. {$ENDIF}
« Last Edit: February 12, 2018, 03:33:36 pm by rvk »

engkin

  • Hero Member
  • *****
  • Posts: 3112
Re: "exception class 'External :?'."
« Reply #6 on: February 12, 2018, 03:34:06 pm »
@rvk: I have two posts above. You saw the second post. The immediate problem is in TTheThread.Execute where he calls OnTerminate without assigning anything to it.

rvk

  • Hero Member
  • *****
  • Posts: 6110
Re: "exception class 'External :?'."
« Reply #7 on: February 12, 2018, 03:37:16 pm »
The immediate problem is in TTheThread.Execute where he calls OnTerminate without assigning anything to it.
I deleted the call to OnTerminate(self) in TTheThread.Execute but for me the code still crashed in TScheduledEvent.Stop;.

Does the code run correctly for you (clicking Start and Stop)?

B.T.W. the problem code you point to isn't even called because the problem already presents itself before TTheThread is ended.
« Last Edit: February 12, 2018, 03:39:55 pm by rvk »

engkin

  • Hero Member
  • *****
  • Posts: 3112
Re: "exception class 'External :?'."
« Reply #8 on: February 12, 2018, 03:56:07 pm »
I did not try to compile it. But after reading your post I did the few obvious changes including changing "Stop Thread" and a quick test seemed to run. Waited a few seconds after hitting "Start Thread" then "Stop Thread" waited more. Closed the app. No crash.

That does not mean the app is ok.

rvk

  • Hero Member
  • *****
  • Posts: 6110
Re: "exception class 'External :?'."
« Reply #9 on: February 12, 2018, 04:00:18 pm »
I did not try to compile it. But after reading your post I did the few obvious changes including changing "Stop Thread" and a quick test seemed to run. Waited a few seconds after hitting "Start Thread" then "Stop Thread" waited more. Closed the app. No crash.
Ok, for topicstarters information: Are you compiling and running on Windows of Linux?

(I still find it strange that all those MSWINDOWS/FPC IFDEFs are really mixed up in Cromis.Scheduler.pas)

engkin

  • Hero Member
  • *****
  • Posts: 3112
Re: "exception class 'External :?'."
« Reply #10 on: February 12, 2018, 04:05:25 pm »
Win32 FPC 3.0.2
I did not look outside unPrincipal. There might be problems in Cromis units as well. Let me check.

BIANCO

  • New member
  • *
  • Posts: 9
  • O Rio!? o Rio é um mundo cara!
Re: "exception class 'External :?'."
« Reply #11 on: February 12, 2018, 04:24:06 pm »
Code: Pascal  [Select][+][-]
  1. destructor TTheThread.Destroy;
  2. begin
  3.   if Assigned(FScheduleTaskList) then
  4.      FreeAndNil(FScheduleTaskList);
  5.  
  6.   if Assigned(FKnowTasks) then
  7.     FreeAndNil(FKnowTasks);
  8.  
  9.   Self.Terminate;
  10.   inherited Destroy;
  11. end;

That does not make sense. Destroy is called after the terminate ( or Terminated := True )

engkin, rvk,

Sorry, so many errors in the example, but I tried several things, I think my example was still polluted.

engkin, I've removed the redundancy of the main Theread destroy but the error persists as rvk said, the problem is in the destruction of the Threads of Cromis lib.

[I'll check the points pointed out by rvk]
« Last Edit: February 12, 2018, 04:25:46 pm by BIANCO »

BIANCO

  • New member
  • *
  • Posts: 9
  • O Rio!? o Rio é um mundo cara!
Re: "exception class 'External :?'."
« Reply #12 on: February 12, 2018, 04:29:07 pm »
I did not try to compile it. But after reading your post I did the few obvious changes including changing "Stop Thread" and a quick test seemed to run. Waited a few seconds after hitting "Start Thread" then "Stop Thread" waited more. Closed the app. No crash.
Ok, for topicstarters information: Are you compiling and running on Windows of Linux?

(I still find it strange that all those MSWINDOWS/FPC IFDEFs are really mixed up in Cromis.Scheduler.pas)

I use Windows 8.1 Pro - 64bit

BIANCO

  • New member
  • *
  • Posts: 9
  • O Rio!? o Rio é um mundo cara!
Re: "exception class 'External :?'."
« Reply #13 on: February 12, 2018, 04:56:11 pm »
I did not try to compile it. But after reading your post I did the few obvious changes including changing "Stop Thread" and a quick test seemed to run. Waited a few seconds after hitting "Start Thread" then "Stop Thread" waited more. Closed the app. No crash.
Ok, for topicstarters information: Are you compiling and running on Windows of Linux?

(I still find it strange that all those MSWINDOWS/FPC IFDEFs are really mixed up in Cromis.Scheduler.pas)

Yes, I noticed, however, as I said this lib was initially made in Delphi, but it should work on Lazarus / FPC.

In the
Code: Pascal  [Select][+][-]
  1. {$ IFDEF FPC}
and MSWindows and
Code: Pascal  [Select][+][-]
  1. {$ IFDEF MSWINDOWS}
directives, both are true since I'm using Lazarus and Windows, right?

I believe the event is being signaled correctly, so much so that the event is triggered, so this is working, right?

Code: Pascal  [Select][+][-]
  1. {$ IFDEF FPC} RTLEventSetEvent {$ ELSE} SetEvent {$ ENDIF} (@ FTermEvent);

The original source I got with Iztok Kacim, I put it in the project source in the Cromis folder.

I do not have much experience with Lazarus + FPC, I used Delphi, I thought this would be easier.
« Last Edit: February 12, 2018, 04:58:30 pm by BIANCO »

rvk

  • Hero Member
  • *****
  • Posts: 6110
Re: "exception class 'External :?'."
« Reply #14 on: February 12, 2018, 05:02:58 pm »
I believe the event is being signaled correctly, so much so that the event is triggered, so this is working, right?

{$ IFDEF FPC} RTLEventSetEvent {$ ELSE} SetEvent {$ ENDIF} (@ FTermEvent);
That line shows that when using FPC (which we are) the RTLEventSetEvent() is used with FTermEvent.

But looking at this:
Code: Pascal  [Select][+][-]
  1.   TCPHandle = {$IFDEF MSWINDOWS}THandle{$ELSE}PRTLEvent{$ENDIF};
and this:
Code: Pascal  [Select][+][-]
  1.     FTermEvent := {$IFDEF MSWINDOWS}CreateEvent(nil, False, False, nil){$ELSE} RTLEventCreate{$ENDIF};
THandle and CreateEvent() is used because MSWINDOWS is also defined in FPC for Windows.

I suspect this code (and the FPC-codes) are added for FPC under Linux. In that case it would all work out.
As it is now, a THandle created by CreateEvent() will be used with the RTLEventCreate() called in .Stop.

So all the {$IFDEF FPC} should be changed to {$IFNDEF MSWINDOWS} so only Windows-calls are used, or some {$IFDEF MSWINDOWS} should be changed to {$IFNDEF FPC}. It depends on the code within.


(I couldn't find Cromis online anymore anywhere)

 

TinyPortal © 2005-2018