5
votes

I use NSTask to run my helper application. On 99% one my customer systems this works fine, but two got back to me letting me know it doesn't. One of them was nice enough to let me look into the issue per remote desktop.

I tried a lot of different NSPipe/NSFileHandle combination for StandardOutput/StandardError to make sure the problem is not related filling up these buffers. Example 1 and 2. My guess is that it is not related because it works fine on so many systems and _dyld_start is too early on in the application lifecycle to fill up StandardOutput/StandardError.

Other notes about the problem:

  • Launching the helper app from the terminal works fine.
  • Attaching and detaching the gdb on the stuck process and after-worth it works fine and when it finished NSTask picks up work after -waitUntilExit.
  • Using fork(2) and execv(3) instead of NSTask is able to launch and run the helper fine.
  • The parent process is sandboxed but I think previous reports where non-sandboxed on Mac OS X 10.6/10.7.

Screenshot of the process Sample from Activity Monitor:

Activity Monitor

Any clues or debugging tips to figure out why the helper is stuck in _dyld_start are welcome!

1
Why are you posting images of textual data? Copy and paste the textual sample report. Also, check for console log messages. And check for DYLD_* environment variables. - Ken Thomases
Seconding the recommendation to check the console. For DYLD_ environment variables, assuming you're not setting them yourself, look in ~/.MacOSX/environment.plist. - Peter Hosey
Console didn't reveal anything. Will check DYLD_ the next time I get access to the machine. - catlan
The symptom is identical to what would happen if you use posix_spawn to launch an application and specify the POSIX_SPAWN_START_SUSPENDED flag, particularly since attaching then detaching gdb unsticks things. NSTask doesn't use posix_spawn though, unless some swizzled version of it is somehow being used. - bdash
And after thinking on this a little more I can't see how DYLD_ variables could be relevant given that the process is stopped before dyld has begun execution. - bdash

1 Answers

-1
votes

Since nobody answered, I am throwing a few ideas. Maybe one of them is the answer – only guessing – but since clues and tips are welcome, you could take a look at:

  • the list of the loaded libraries in the crash dump (there may be a clue there)
  • any error that would happen in the child process (after the fork). However, I see why it could be difficult to get back any post-fork error.

If I recall correctly, NSTask calls posix_spawn(2). This may be a clue, since using fork(2) and execv(3) seems working, you could focus on the differences between NSTask and the non-blocking alternative. Clearly, something is happening at the very beginning that prevents the child from executing properly.

  • Are you sure it is stuck and not crashed? As far as the user could tell, your app your app wouldn't look like it crashed. Only the child process would crash.
  • As a last resort, you could try to look for any Mach exception occuring (if any, that would mean an error, which you wouldn't be able to recover anyway. But it would provide valuable clues nonetheless).
  • You can tell willing custommers to send you their sysdiagnose.
    To this goal, ask them to hit Command + Option + Control + . + Shift to wait a few minutes. Soon after, their finder should pop a window to reveal a file named: sysdiagnose_timestamp_.tar.gz. Kindly ask them to mail it to you. Mine is around 5 MB. More details on the sysdiagnose man page.