Recent

Author Topic: [SOLVED] WaitForMultipleObjects, prob with EventArray (ERROR_INVALID_HANDLE)  (Read 2696 times)

d7_2_laz

  • Hero Member
  • *****
  • Posts: 640
Porting a Delphi 7 app to Lazarus 2.0.12 Windows x84 i  a component  i used since years with Delphi  is combinding ReadDirectoryChangesW with WaitForMultipleObjects.

An Event "FileEvent" is watching for folder changes and is functionally working fine when used as a single argument within WaitForMultipleObjects.

Code: Pascal  [Select][+][-]
  1. var  FileEvent : THandle:
  2.      SuspEvent : TEvent;  SuspEvName : String;
  3.      TermEvent : TEvent;  TermEvName : String;
  4.  
  5. FileEvent:=CreateEvent(nil,FALSE,FALSE,nil);
  6. TermEvent:=TEvent.Create(nil,FALSE,FALSE,TermEvName);
  7. SuspEvent:=TEvent.Create(nil,FALSE,FALSE,SuspEvName);
  8.  
  9. // Only one argument, and it works fine:
  10. WaitResult := WaitForMultipleObjects(1, @FileEvent, FALSE, infinite);
  11.  

But now, each attempt i test to use this FileEvent within an EventArray unfortunately fails with
a WaitResult  WAIT_FAILED  (=4294967295), where GetLastError is 6 = ERROR_INVALID_HANDLE.

Code: Pascal  [Select][+][-]
  1. var EventArray: Array[0..2] of THandle;
  2. EventArray[0] := FileEvent; // Changes within folder
  3. EventArray[1] := THandle(TermEvent.Handle);  // Abirt
  4. EventArray[2] := THandle(SuspEvent.Handle) ; // Suspend
  5.  
  6. WaitResult := WaitForMultipleObjects(3, @EventArray, FALSE, infinite);   // --> WAIT_FAILED; ERROR_INVALID_HANDLE
  7. //WaitResult := WaitForMultipleObjects(3, @EventArray[0], FALSE, infinite);  // --> WAIT_FAILED; ERROR_INVALID_HANDLE
  8. //WaitResult := WaitForMultipleObjects(3, PWOHandleArray(@EventArray), FALSE, infinite);   // --> WAIT_FAILED; ERROR_INVALID_HANDLE
  9.  

Can anybody give a clue how to pass those arguments correctly to WaitForMultipleObjects in Lazarus?

« Last Edit: March 27, 2021, 04:29:17 pm by d7_2_laz »
Lazarus 4.0  FPC 3.2.2 Win10 64bit

d7_2_laz

  • Hero Member
  • *****
  • Posts: 640
Re: WaitForMultipleObjects, prob with EventArray (ERROR_INVALID_HANDLE)
« Reply #1 on: March 27, 2021, 02:06:41 am »
Hello jamie, thank you!
I guess you refer to the WaitForMultipleObjects resulting var "WaitResult"?
It's defined as DWORD and evaluated subsequently via case of, as of such
Code: Pascal  [Select][+][-]
  1.         case WaitResult of
  2.             WaitDir:   ......         // WAIT_OBJECT_0
  3.             WaitTerm:  .....          // WAIT_OBJECT_0+1
  4.             WaitSusp:  ......         // WAIT_OBJECT_0+2
  5. etc.

and those are entered quite as desired when having done before:
Code: Pascal  [Select][+][-]
  1. WaitResult := WaitForMultipleObjects(1, @FileEvent, FALSE, infinite);

but not when doing before (in any flavours i did try):
Code: Pascal  [Select][+][-]
  1. WaitResult := WaitForMultipleObjects(3, @EventArray, FALSE, infinite);   // --> WAIT_FAILED; ERROR_INVALID_HANDLE
  2. // or EventArray or @EventArray[0] or PWOHandleArray(@EventArray) or such

So i would feel that it may be around the data type evaluaion resp. assumption for the contents of the elements of the array.
"FileEvent" is THandle .... and it can be used ok when used as a single argument
"SuspEvent" etc. is  TEvent, but the Handle of it is thrown into the array
"EventArray" is an Array of THandle. So that would look good to me, but obviously it is not (maybe x64 specific .., or pointe/THandle mismatch when converting).
Probably it's due my own coding, but i'm in a lack to understand what might go wrong.Tricky.
Lazarus 4.0  FPC 3.2.2 Win10 64bit

PascalDragon

  • Hero Member
  • *****
  • Posts: 6049
  • Compiler Developer
Re: WaitForMultipleObjects, prob with EventArray (ERROR_INVALID_HANDLE)
« Reply #2 on: March 27, 2021, 11:33:26 am »
with FPC Booleans may end up being -1 for true where as in windows may expect 1 has a true value and 0 otherwise..

Wrong way round. The types Boolean, Boolean8, Boolean16, Boolean32 and Boolean64 use 1 for True and 0 for False. The types ByteBool, WordBool, LongBool and QWordBool use not 0 for True and 0 for False. Especially LongBool is the one that is supposed to be used for WinAPI BOOL types (and that's in fact how BOOL is declared in both FPC and Delphi).

Also FPC correctly converts True and False to the corresponding Boolean type (and also between them).

Can anybody give a clue how to pass those arguments correctly to WaitForMultipleObjects in Lazarus?

As it is right now you can't use TEvent.Handle in Windows Wait*-functions, because it's not a THandle, but instead a record containing the real handle and the last error (though I really wonder why it was done this way). So either use CreateEvent directly or retrieve the real handle using the following record (taken from rtl/win/systhrd.inc):

Code: Pascal  [Select][+][-]
  1. type Tbasiceventstate=record
  2.                         fhandle    : THandle;
  3.                         flasterror : longint;
  4.                        end;
  5.      plocaleventrec= ^tbasiceventstate;

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12326
  • FPC developer.
Re: WaitForMultipleObjects, prob with EventArray (ERROR_INVALID_HANDLE)
« Reply #3 on: March 27, 2021, 01:07:28 pm »
If you can make a small self contained example from it that we can test under delphi and FPC we maybe can get a bit deeper into this.

d7_2_laz

  • Hero Member
  • *****
  • Posts: 640
Re: WaitForMultipleObjects, prob with EventArray (ERROR_INVALID_HANDLE)
« Reply #4 on: March 27, 2021, 02:08:10 pm »
PascalDragon,
your explanation fully makes sense to me,  as i already suspected event #2 nd #3 (SuspEvent  TermEvent: TEvent ... created via TEvent.Create) to be the culprits, as event #1 ((FileEvent: THandle  ... created via CreateEvent) did work fine "stand-alone"
Code: Pascal  [Select][+][-]
  1. EventArray[0] := FileEvent;
  2. WaitResult := WaitForMultipleObjects(1, @EventArray, FALSE, infinite);   // with "1" it does work fine

So, yes, i'm convinced it's indeed that handle interpretation of event #2 and #3 - the origin of the issue is that something like:
EventArray[1] := THandle(TermEvent.Handle);
does satisfy the compiler, but is not that what the WaitForMultipleObjects does expect.

For the solution i'd prefer to "retrieve the real handle" using the Tbasiceventstate structure but am unsure how to do that exactly.
Looking into an example usage of it within systhrd.inc, i understand:
it would require a mem New and Dispose, but the assignment to the FHandle property itself uses an CreateEvent here:
Code: Pascal  [Select][+][-]
  1. plocaleventrec(result)^.FHandle := CreateEvent(EventAttributes, AManualReset, InitialState,n);

Can we do such to if we already have an Event of type TEVent created, and how?
By something like:
Code: Pascal  [Select][+][-]
  1. plocaleventrec(result)^.FHandle := TermEvent.Handle;   // ??? Possible?? Hum
?

marcov.
yes i know that a small example would be useful, but it is not easy because it's buried within a lot of other stuff. Would need to be recreated nearly from the scratch.
Lazarus 4.0  FPC 3.2.2 Win10 64bit

PascalDragon

  • Hero Member
  • *****
  • Posts: 6049
  • Compiler Developer
Re: WaitForMultipleObjects, prob with EventArray (ERROR_INVALID_HANDLE)
« Reply #5 on: March 27, 2021, 04:02:20 pm »
For the solution i'd prefer to "retrieve the real handle" using the Tbasiceventstate structure but am unsure how to do that exactly.

You simply need to cast correctly:

Code: Pascal  [Select][+][-]
  1.   EventArray[0] := FileEvent;
  2.   EventArray[1] := plocaleventrec(TermEvent.Handle)^.fhandle;
  3.   EventArray[2] := plocaleventrec(SuspEvent.Handle)^.fhandle;
  4.  

d7_2_laz

  • Hero Member
  • *****
  • Posts: 640
Uh, so easy  ... Yep, that's it? The issue is away.
I think now i do understand better: it appears to me that the TEvent's "Handle" property is a slighly misleading identifier for an object that in fact needs to stripped down into appropriate parts to retrieve the real Handle part. Right?
Lazarus 4.0  FPC 3.2.2 Win10 64bit

PascalDragon

  • Hero Member
  • *****
  • Posts: 6049
  • Compiler Developer
Re: WaitForMultipleObjects, prob with EventArray (ERROR_INVALID_HANDLE)
« Reply #7 on: March 27, 2021, 05:34:05 pm »
I don't know what to tell you...

 every test I run I see $FFFFFFFFFF etc for a True Boolean no matter that case and that results into a -1 value

Please give me code example where the compiler actually generates a true value 1 for a TRUE statement in a function call header, I have searched and It can't be found on my end..
I have created hacks in fpc for API calls due to this issue where it wants to see 0 or 1 for Booleans but fpc sends it -1 instead.

The following program:

Code: Pascal  [Select][+][-]
  1. program tbool;
  2.  
  3. procedure Test(aArg1: Boolean; aArg2: LongBool);
  4. begin
  5.   Writeln(HexStr(Ord(aArg1), SizeOf(aArg1) * 2));
  6.   Writeln(HexStr(Ord(aArg2), SizeOf(aArg2) * 2));
  7. end;
  8.  
  9. begin
  10.   Test(True, True);
  11. end.

Will write:

Code: [Select]
PS C:\fpc\git> .\testoutput\tbool.exe
01
FFFFFFFF

So request back to you: please provide an example that demonstrates your issue.

 

TinyPortal © 2005-2018