fork within Cocoa application

2019-02-14 04:52发布

问题:

My problem is not the best scenario for fork(). However, this is the best func I can get.

I am working on a Firefox plugin on Mac OSX. To make it robust, I need to create a new process to run my plugin. The problem is, when I forked a new process, much like this:

if (fork() == 0) exit(other_main());

However, since the state is not cleaned, I cannot properly initialized my new process (call NSApplicationLoad etc.). Any ideas? BTW, I certainly don't want create a new binary and exec it.

回答1:

In general, you need to exec() after fork() on Mac OS X.

From the fork(2) man page:

There are limits to what you can do in the child process. To be totally safe you should restrict your-self to only executing async-signal safe operations until such time as one of the exec functions is called. All APIs, including global data symbols, in any framework or library should be assumed to be unsafe after a fork() unless explicitly documented to be safe or async-signal safe. If you need to use these frameworks in the child process, you must exec. In this situation it is reasonable to exec yourself.

TN2083 also comments on this subject:

Many Mac OS X frameworks do not work reliably if you call fork but do not call exec. The only exception is the System framework and, even there, the POSIX standard places severe constraints on what you can do between a fork and an exec.

IMPORTANT: In fact, in Mac OS X 10.5 and later, Core Foundation will detect this situation and print the warning message shown in Listing 13.

Listing 13: Core Foundation complaining about fork-without-exec

The process has forked and you cannot use this CoreFoundation functionality safely. You MUST exec(). Break on __THE_PROCESS_HAS_FORKED_AND_YOU_CANNOT_USE_THIS_COREFOUNDATION_FUNCTIONALITY___YOU_MUST_EXEC__() to debug.



回答2:

fork without exec is basically entirely unsafe on OSX. You will end up with stale mach ports for example.



回答3:

I'm writing the FreeWRL plugin for Firefox (Linux at the moment, Mac & Windows soon).

http://freewrl.sourceforge.net/

It's based on fork+exec to launch FreeWRL and swallow its window into Firefox.

You'll have to use a pipe to correctly handle the possible failure of fork+exec or the failure of your child process :

How to handle execvp(...) errors after fork()?

Cheers, C



标签: cocoa macos fork