Reputation: 2070
I have an Objective-C app that is using NSUserAppleScriptTask to call some Applescript. The applescript is returning a string that can vary in size.
It works fine with the string is short. However, when it gets very long, it starts failing silently. If it attempts to return a string that is 40,000 characters long, the completionHandler
will never be called, and the string returned ...
is never printed. No messages to the log, no messages to the console. It is just never called.
A string of 30,000 characters works fine. I'm not sure where the precise cutoff is.
Has anyone seen this before? Is there a property or configuration setting I could change to increase this limit? Or do I just need to give up on NSUserAppleScriptTask?
NSURL* scriptURL = [[NSBundle mainBundle] URLForResource:@"ApplescriptHelper" withExtension:@"scpt"];
NSError* error;
NSUserAppleScriptTask* task = [[NSUserAppleScriptTask alloc] initWithURL:scriptURL error:&error];
NSLog(@"created task %@, error %@", task, error);
/* CREATE APPLE EVENT */
// taken from https://www.objc.io/issues/14-mac/sandbox-scripting/
ProcessSerialNumber psn = {0, kCurrentProcess};
NSAppleEventDescriptor *target = [NSAppleEventDescriptor descriptorWithDescriptorType:typeProcessSerialNumber bytes:&psn length:sizeof(ProcessSerialNumber)];
NSAppleEventDescriptor *function = [NSAppleEventDescriptor descriptorWithString:@"test"];
NSAppleEventDescriptor *event = [NSAppleEventDescriptor appleEventWithEventClass:kASAppleScriptSuite eventID:kASSubroutineEvent targetDescriptor:target returnID:kAutoGenerateReturnID transactionID:kAnyTransactionID];
[event setParamDescriptor:function forKeyword:keyASSubroutineName];
/* END CREATE APPLE EVENT */
[task executeWithAppleEvent:event completionHandler:^(NSAppleEventDescriptor*resultEventDescriptor, NSError *error) {
NSLog(@"returned %@, error %@", resultEventDescriptor, error);
if (!resultEventDescriptor) {
NSLog(@"%s AppleScript task error = %@", __PRETTY_FUNCTION__, error);
} else {
NSLog(@"success")
}
}];
on test()
set str to ""
repeat 40000 times
set str to str & "x"
end repeat
return str
end fetchMusic
Upvotes: 0
Views: 343
Reputation: 36
This looks like an Apple bug. You should file a report.
Running your code, osascript
stalls with the following call graph:
+ 2812 start (in libdyld.dylib) + 8 [0x7fff97a205b4]
+ 2812 exit (in libsystem_c.dylib) + 55 [0x7fff9157f403]
+ 2812 __cxa_finalize_ranges (in libsystem_c.dylib) + 345 [0x7fff9157f0ff]
+ 2812 std::__1::ios_base::Init::~Init() (in libc++.1.dylib) + 16 [0x7fff8f1ebd98]
+ 2812 std::__1::basic_ostream<char, std::__1::char_traits<char> >::flush() (in libc++.1.dylib) + 68 [0x7fff8f1e2f5a]
+ 2812 std::__1::__stdoutbuf<char>::sync() (in libc++.1.dylib) + 137 [0x7fff8f1ec30d]
+ 2812 fflush (in libsystem_c.dylib) + 40 [0x7fff9155c31c]
+ 2812 __sflush (in libsystem_c.dylib) + 87 [0x7fff9155c3c0]
+ 2812 _swrite (in libsystem_c.dylib) + 87 [0x7fff91563e96]
+ 2812 __write_nocancel (in libsystem_kernel.dylib) + 10 [0x7fff918e57ba]
I think you're running into the pipe buffer limit of 65536 bytes.
If you play with the undocumented osascript
arguments that NSUserAppleScriptTask
uses, you get raw AppleEvent output with a 16-byte header & UTF-16
encoded text.
Anything over 32760
in your repeat
loop causes this behavior. 32760
* 2
+ 16
= 65536
.
Upvotes: 2