Timeout constants are broken on -[NSAppleEventDescriptor sendEventWithOptions:timeout:error:]

Originator:automate.mantasystems
Number:rdar://21477694 Date Originated:21-Jun-2015 06:24 PM
Status:Open Resolved:
Product:OS X Product Version:OS X 10.11 (15A178w)
Classification:Bug Reproducible:Always
 
Summary:
Whereas the Carbon AEMSendMessage function takes a timeout value in ticks, the new -[NSAppleEventDescriptor sendEventWithOptions:timeout:error:] method (rdar://19169736) accepts a timeout value in seconds (NSTimeInterval). 

This is not a problem when the timeout is an arbitrary non-negative float (e.g. 30.0 = 30 seconds). However, it fails to work correctly when one of the standard timeout constants - kAEDefaultTimeout, kNoTimeOut - is given. AEDataModel.h defines these constants as follows:

/* Constants for timeout durations */
enum {
  kAEDefaultTimeout             = -1,   /* timeout value determined by AEM */
  kNoTimeOut                    = -2    /* wait until reply comes back, however long it takes */
};

It appears that the current sendEvent... implementation converts the given timeout-in-seconds to ticks by multiplying by 60 then casting to long, but fails to treat negative floats as a special case.

The simplest solution would be to modify the method implementation so that negative timeout values are not multiplied but are simply cast to long as-is, thus ensuring the existing constants continue to work as expected. For example (https://bitbucket.org/hhas/appleeventbridge/src/7995324fde315eb830c669f2b1a4c7b8dd069614/AppleEventBridge/NSAppleEventDescriptor+AEDescExtensions.m?at=swift-support):

- (instancetype)sendEventWithOptions:(AESendMode)sendOptions timeout:(NSTimeInterval)timeoutInSeconds error:(NSError * __autoreleasing *)error {
    if (error) *error = nil;
    AEDesc reply = {typeNull, NULL};
    OSStatus err = AESendMessage(self.aeDesc, &reply, sendOptions, (long)(timeoutInSeconds > 0 ? timeoutInSeconds * 60 : timeoutInSeconds)); // FIX
    if (err != noErr) {
        if (error) *error = [NSError errorWithDomain: NSOSStatusErrorDomain code: err userInfo: nil];
        return nil;
    }
    return [[self.class alloc] initWithAEDescNoCopy: &reply];
}

Steps to Reproduce:


Expected Results:


Actual Results:


Version:
OS X 10.11 (15A178w)
Xcode Version 7.0 beta (7A120f)

Notes:
NSAppleEventDescriptor.h now aliases the old AESendMode constants from AEDataModel.h as NSAppleEventSend.. constants for use in the new -sendMessage method. It would be helpful if the following constants from AEDataModel.h could be similarly aliased as these are also required in creating and sending events via NSAppleEventDescriptor:

/* Constants for timeout durations */
enum {
  kAEDefaultTimeout             = -1,   /* timeout value determined by AEM */
  kNoTimeOut                    = -2    /* wait until reply comes back, however long it takes */
};


enum {
                                        /* Constant for the returnID param of AECreateAppleEvent */
  kAutoGenerateReturnID         = -1,   /* AECreateAppleEvent will generate a session-unique ID */
                                        /* Constant for transaction IDs */
  kAnyTransactionID             = 0     /* no transaction is in use */
};

Comments


Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!