Watch, Follow, &
Connect with Us
Public Report
Report From: Delphi-BCB/RTL/Delphi/Other RTL    [ Add a report in this area ]  
Report #:  103732   Status: Withdrawn
TOCGenericImport<>.Wrap issues when storing result in variable outside of the calling procedure
Project:  Delphi Build #:  16.0.4358.45540
Version:    16.3 Submitted By:   Erik van Bilsen
Report Type:  Crash / Data loss / Total failure Date Reported:  2/27/2012 12:23:00 PM
Severity:    Serious / Highly visible problem Last Updated: 2/27/2012 12:40:06 PM
Platform:    All Mac platforms Internal Tracking #:  
Resolution: None  Resolved in Build: : None
Duplicate of:  None
Voting and Rating
Overall Rating: No Ratings Yet
0.00 out of 5
Total Votes: None
Description
This issue is a bit difficult to explain. We use NSRunningApplication to get access to a running application on OSX. But I don't think this issue is specific to NSRunningApplication, but can happen with other Objective-C classes as well.

To create a NSRunningApplication object using a given process ID, you use the following code;

  AppPtr := TNSRunningApplication.OCClass.runningApplicationWithProcessIdentifier(ProcessID);
  if Assigned(AppPtr) then
    FApp := TNSRunningApplication.Wrap(AppPtr);

Here, FApp is a field in some class, so we can reference is later. Then, when we later want to hide this application, we call:

if Assigned(FApp) then
  FApp.hide;

However, this will crash or freeze the application (not the target application you try to hide, but the FireMonkey source application). If you run the app outside of the debugger, the following message is sent to the PAServer terminal window before the application freezes:

[NSEvent hide]: unrecognized selector sent to instance...

A workaround is to not keep a hold of the NSRunningApplication object and recreate it locally every time you need it:

  AppPtr := TNSRunningApplication.OCClass.runningApplicationWithProcessIdentifier(ProcessID);
  if Assigned(AppPtr) then
  begin
    App := TNSRunningApplication.Wrap(AppPtr);
    App.hide;
  end;

This works as expected. However, we don't want to recreate this object everytime for efficiency reasons (we interrogate the running application a lot).

I don't know what the source of this issue is. I don't think it is NSRunningApplication specific, but has to do with the way how Objective-C objects are wrapped (using TOCGenericImport) and the references are kept.

I tried to add a FApp._addref call to make sure the reference stays alive, but that makes no difference.
Steps to Reproduce:
Run the attached sample application.

When you click the first button, the global FApp reference will be used. This will likely result in a freeze or crash of the application.

When you click the second button, everything works as expected.
Workarounds
See Description
Attachment
NSRunningApplication Wrapper.zip
Comments

None

Server Response from: ETNACODE01