Jump to content
Incus J

Invalid Compiler Directive: 'MESSAGES'

Recommended Posts

That sounds good.  I've just tested the latest overnight zip, and D104InstallVclFmx builds successfully for macOS 64-bit.

 

The sample app IcsHttpsTst builds successfully by adding the Ics.Fmx. prefix to a few IcsHttpTst1.pas uses units.

 

When the sample app deploys and runs on macOS 64-bit I get an ERangeError "Range check error" at runtime.  I think it occurs in Ics.Posix.Messages.pas but the IDE debugger can't find that unit, so I'm not sure.  I must need to tell the IDE/Debugger the path to the ICS source units so it can step into them - but I'm not sure how to do this.  The Delphi compiler already knows where the source units are, because the app builds and deploys OK, but the IDE itself seems unaware at the moment.

Edited by Incus J

Share this post


Link to post

Pleased you got the package built, I've put updating the sample uses sections on my list. 

 

Sorry, never tried debugging a non-windows platform. 

 

I have been wondering why ICS is using a lot of MacOS specific libraries to emulate Windows messages, when the FMX forms unit seems to have ProcessMessages which one assumes works similarly to the Windows forms unit, it might be early versions of FMX 10 years ago were more limited.  But I have other delayed projects to finish and can not investigate yet.

 

Angus

 

Share this post


Link to post

I remember back in Delphi 10.2 Tokyo FMX ProcessMessages seemed to behave differently to VCL ProcessMessages.

 

With VCL I can call ProcessMessages and any queued mouse clicks are processed.

With FMX I found that a call to ProcessMessages did not process queued mouse clicks.

 

It was as though FMX UI events were handled separately.  I don't know whether this is still the case.

Share this post


Link to post

On a Windows form the entire application runs from ProcessMessages, if that is not the case with FMX then I guess it's a different design concept.

 

Angus

 

Share this post


Link to post

I think FMX renders its UI to a surface/canvas, rather than having the OS render the controls (?) - so yes, it could be different.

 

This is where the IcsHttpsTst seems to get stuck at startup:  Line 1962 of Ics.Posix.Messages

function TMultiReadExclusiveWriteSynchronizer.BeginWrite: Boolean;
var
  Thread: PThreadInfo;
  HasReadLock: Boolean;
  ThreadID: Cardinal;
  Test: Integer;
  OldRevisionLevel: Cardinal;
begin
...
ThreadID := GetCurrentThreadID;

The top of the call stack looks like this :

 

:000000010001D0F0 System::_DbgExcNotify(int, void*, System::SmallString<(unsigned char)255>*, void*, void*)
:000000010001D12E System::NotifyReRaise(System::TObject*, void*)
:000000010001D1CA System::_RaiseAtExcept(System::TObject*, void*)
:0000000100056AB8 System::Sysutils::ErrorHandler(unsigned char, void*)
:0000000100015F30 System::ErrorAt(unsigned char, void*)
:000000010001B252 System::_BoundErr()
Ics.Posix.Messages.TMultiReadExclusiveWriteSynchronizer.BeginWrite()(0x0000000102521120)
Ics.Posix.Messages.TIcsMessagePump.AfterConstruction()(0x000000020245bd80)
:0000000100016B45 System::_AfterConstruction(System::TObject*)
:0000000100011443 System::TObject::TObject()
Ics.Fmx.Overbyteicswndcontrol.TIcsWndControl.AllocateHWnd()(0x0000000203080ff0)
Ics.Fmx.Overbyteicshttpprot.THttpCli.THttpCli(System.Classes.TComponent*)(0x0000000203080ff0,true,0x000000020801e5f0)

...

 

Maybe that contains useful information.  On Posix, the System unit defines:

TThreadID = NativeUInt;

But local var ThreadID is Cardinal.  Maybe Cardinal and NativeUInt are not compatible.  If I redefine ThreadID as a NativeUInt too, then the ERangeError disappears, and the app is "[Running]" - but the UI does not appear.  I think Thread #1 might be waiting for something.

Edited by Incus J

Share this post


Link to post

ThreadID: Cardinal; should really be ThreadID: TThreadID; to match all other use in the unit.  Perhaps there is another mismatch somewhere that has caused truncation or something?

 

Angus

 

Share this post


Link to post
20 hours ago, Angus Robertson said:

I have been wondering why ICS is using a lot of MacOS specific libraries to emulate Windows messages, when the FMX forms unit seems to have ProcessMessages which one assumes works similarly to the Windows forms unit, it might be early versions of FMX 10 years ago were more limited.  But I have other delayed projects to finish and can not investigate yet.

Could FMX message queue be used in console applications?

Share this post


Link to post

ICS Windows console applications need a message pump anyway, and are relatively rare.  I only have a single console application that sends emails when SVN is updated. 

 

An old version of ICS supported Kylix with a message pump which we could bring up to date, but if FMX supports this already, that is faster.

 

Angus

 

Share this post


Link to post
6 hours ago, Angus Robertson said:

ICS Windows console applications need a message pump anyway, and are relatively rare.  I only have a single console application that sends emails when SVN is updated.

Well, I have several 24/7 network apps that I'd make console or service if I were starting them now. And as we're slowly moving to Linux, it's very common for it to have no GUI at all on servers

Share this post


Link to post
Quote

it's very common for it to have no GUI at all on servers

Quite true, I use ICS in several Windows services.  However all windows services need a message loop, that is how they are stopped and controlled.  Obviously not the case with Linux.

 

Angus

 

Share this post


Link to post

I had to port only the TCP part of the ICS to OSX64 and I identified what the translation of the kevent and probably of the kevent_64 structures is inaccurate: the uint32_t, the data type of the fflags field should be not LongWord, but Cardinal.  And the {$A4} directive should be removed for the kevent record. This way it works on both OSX32 and OSX64. I tried with Delphi 10.3.3.

Edited by gyk

Share this post


Link to post

Thanks for joining this thread and helping to get ICS working on MacOs64. 

 

I've updated Ics.Posix.KEventTypes,pas with your fixes, but am wondering whether I should also be changing WSocket to use EV_SET64 and TKEvent64 instead of EV_SET in TIcsEventQueue?  Or does MacOS64 support both.  Not in SVN yet.

 

I don't believe there is much point in trying to retain MacOS32 compatibility going since 10.4 no longer supports it. 

 

Regarding your off-list comment about TMultiReadExclusiveWriteSynchronizer and ThreadID, I did change this to ThreadID: TThreadID; last week to match all other instances. 

 

Please be aware I can now build for Linux64 but not for MacOS since  don't have any Apple hardware, so I can catch general Posix compiler issues, but not Mac only issues.  And the Linux message handler is not done yet. 

 

Angus

Share this post


Link to post
51 minutes ago, Angus Robertson said:

Thanks for joining this thread and helping to get ICS working on MacOs64. 

 

I've updated Ics.Posix.KEventTypes,pas with your fixes, but am wondering whether I should also be changing WSocket to use EV_SET64 and TKEvent64 instead of EV_SET in TIcsEventQueue?  Or does MacOS64 support both.  Not in SVN yet.

 

I don't believe there is much point in trying to retain MacOS32 compatibility going since 10.4 no longer supports it. 

 

Regarding your off-list comment about TMultiReadExclusiveWriteSynchronizer and ThreadID, I did change this to ThreadID: TThreadID; last week to match all other instances. 

 

Please be aware I can now build for Linux64 but not for MacOS since  don't have any Apple hardware, so I can catch general Posix compiler issues, but not Mac only issues.  And the Linux message handler is not done yet. 

 

Angus

kevent is usable on MacOS64 as well. It confused me as well but as I understood later the benefit of kevent_64 what it can hold some additional data  So I think you don't have to switch to kevent_64.

 

Btw technically you can run MacOs in the WmVare player 15 free edition on Widows host if you have enough RAM. in your PC.

 

György

Edited by gyk

Share this post


Link to post

The latest overnight zip looks good.  I can get both IcsHttpsTst and also my own app to Build successfully for macOS 64-bit (but not run successfully at present).

 

IcsHttpsTst hangs when it starts up (the main form is never displayed).

My own app runs OK, and is functional until it tries to use ICS - at which point it hangs too.

 

Both apps are actually still running, but seem stuck in an infinite loop.  If I select Program Pause from the IDE, a CPU tab appears filled with assembly language, showing the current execution point in Thread #1.  I can perform commands such as Run Until Return.

Thread #1
-> 00007FFF6E68AE36 C3               ret 
   00007FFF6E68AE37 90               nop 
   00007FFF6E68AE38 4989CA           mov r10, rcx
   00007FFF6E68AE3B B825000001       mov eax, 0x1000025
   00007FFF6E68AE40 0F05             syscall 
   00007FFF6E68AE42 C3               ret 
   00007FFF6E68AE43 90               nop 
   00007FFF6E68AE44 4989CA           mov r10, rcx
   00007FFF6E68AE47 B826000001       mov eax, 0x1000026
   00007FFF6E68AE4C 0F05             syscall 

Is there a 'Run Until Inside A Delphi Unit' command somewhere?

Share this post


Link to post

Thank you Lars - I wasn't sure as Trace to Next Source Line just hangs again - so it must never reach a Delphi Source Line to stop at.  Which makes sense if it is stuck in an infinite loop somewhere - I guess that means it's getting stuck in the system somewhere outside of Delphi code.

Share this post


Link to post

I've had a go at stepping through code from my app.  It's a bit tricky because the units such as Ics.Fmx.OverbyteIcsWndControl contain no actual code, just an include {$I OverbyteIcsWndControl.pas}, which the Debugger isn't pulling in, so I don't get to see the lines of code I Trace Into or Step Over in the IDE.  It is stepping though, because the call stack changes when I press F7, and I occasionally step into the System unit.

 

Shortly before the hang, the call stack looks like this :

Ics.Fmx.Overbyteicshttpprot.THttpCli.SetTerminated(bool)(0x0000000203a33170,false)
Ics.Fmx.Overbyteicswndcontrol.TIcsWndControl.TIcsWndControl(System.Classes.TComponent*)(0x0000000203a33170,false,0x000000020bd3b640)
Ics.Fmx.Overbyteicshttpprot.THttpCli.THttpCli(System.Classes.TComponent*)(0x0000000203a33170,true,0x000000020bd3b640)

And the hang occurs after/when the System unit executes :

constructor TObject.Create;
begin
end;

Oh, here we go - this looks more useful :

:00007FFF6E68AE36 semaphore_wait_trap
:00007FFF6E4F0AED _dispatch_sema4_wait
:00007FFF6E4F0FBF _dispatch_semaphore_wait_slow
System.Syncobjs.TEvent.WaitNoReset(unsigned int)(0x0000000205815ff0,4294967295)
System.Syncobjs.TEvent.WaitFor(unsigned int)(0x0000000205815ff0,4294967295)
Ics.Posix.Messages.TMultiReadExclusiveWriteSynchronizer.WaitForWriteSignal()(0x0000000105809620)
Ics.Posix.Messages.TMultiReadExclusiveWriteSynchronizer.BeginWrite()(0x0000000105809620)
Ics.Posix.Messages.TIcsMessagePump.AfterConstruction()(0x000000020beeb1b0)
System._AfterConstruction(System.TObject*)(0x000000010bed9a40)
System.TObject.TObject()(0x000000010bed9a40,true)
Ics.Fmx.Overbyteicswndcontrol.TIcsWndControl.AllocateHWnd()(0x0000000203a33170)
Ics.Fmx.Overbyteicshttpprot.THttpCli.THttpCli(System.Classes.TComponent*)(0x0000000203a33170,true,0x000000020bd3b640)

So the app hangs at semaphore_wait_trap.  Not sure what that is yet, but there is a Thread #7 labelled :

 

TIcsAsyncSocketThread (7) with the following Call Stack

kevent
Ics.Fmx.Overbyteicswsocket.TIcsEventQueue.HandleEvents()
Ics.Fmx.Overbyteicswsocket.TIcsAsyncSocketThread.Execute()
System.Classes.ThreadProc(System.Classes.TThread*)
System.ThreadWrapper(void*)
_pthread_start
thread_start

Could Thread #1 be waiting for Thread #7 to complete or sync?  Other threads do exist (4, 10, 14, 19) but are all unlabelled.

Edited by Incus J

Share this post


Link to post
On 9/25/2020 at 3:21 PM, Incus J said:

Thank you Lars - I wasn't sure as Trace to Next Source Line just hangs again - so it must never reach a Delphi Source Line to stop at.  Which makes sense if it is stuck in an infinite loop somewhere - I guess that means it's getting stuck in the system somewhere outside of Delphi code.

It quite often doesn't work. I blame the debugger.
One thing that helps a little, is to make sure that you switch the active thread to the one where you expect the break - but it is no guarantee.

Share this post


Link to post

Thanks Lars.  I had no luck switching thread, but found the routine mentioned in the call stack manually.  It is useful that the code gives the thread a label in Debug mode.  I've set a Breakpoint prior to the hang so I can step through the code and see what parameters are being passed in.  Unfortunately Breakpoints don't seem to be working in this unit.  Breakpoints look to be set OK at design time, but become unavailable (X) at runtime, so the program runs past.

 

394627394_BreakpointUnavailable.thumb.png.1504bd7d4e885af384c81d114046b45a.png

 

 

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×