NSTask Problems on Solaris

Creation Date: May 8, 1998
Keywords: Solaris, HP-UX, NSTask, fork

Q: Why won't NSTasks run under Solaris?

A: On Solaris, the fork() command is used only in non-threaded contexts; fork1() is used for multithreaded applications.  Because Apple's implementation of NSTask in WebObjects release 3.5.1 does not conform to this usage, you will not be able to use NSTasks on the Solaris platform.  Instead, you will have to use fork1() and exec() to manually spawn a process.  

This code example shows how an external task might be set up to run with fork and exec for Solaris and HP-UX systems, and with NSTask for other OpenStep platforms.

- (oneway void)startAppWithInstanceDict:(NSMutableDictionary*)instanceDict {

// if solaris or hpux--make sure the NeXT_PDO and _svr4_ varaiables are defined
#if ((NeXT_PDO && (__svr4__ || hpux)) || __hpux)

	{
	//Use fork and exec to launch a task manually for Solaris (and HP-UX) systems.

	// we need to build a command string that will look like:
	// DocumentPath/exec -a WODefaultAdaptor -n instanceNumber -p portNumber -d DocumentPath
	// executable path ...

	int€€€€pid;
	int€€€€€€€€execReturnValue;
	NSString * cmdString;
	NSEnumerator *stringEnum;
	NSString *aString;
	char *cpath, **argvp;
	int nargs, n;
	int maxfds = getdtablesize();

	NSLog(@"Executing non-Mach or non-NT code");

	//Determine whether we should use fork() (for HP-UX systems) or fork1() (for Solaris)

	#if (hpux || __hpux)
	switch ( pid = fork() )
	#else
	switch ( pid = fork1() )
	#endif
		{
		case 0:
			NSLog(@"Enter child process fork(), maxfds = %d", maxfds);

			// for ( n = 3; n < maxfds; n++)
				{
				//€€€€ NSLog(@"Closing descriptor %d, retval = %d", n, close(n));
				//€€€€ close(n);
				}
	
			cpath = [fullExePath fileSystemRepresentation];
			nargs = [cmdArray count];
			argvp = NSZoneMalloc(NULL, (2 + nargs) * sizeof (*argvp));
			argvp[0] = (char *)cpath;
			for (n=0; n < nargs; ++n)
				{
				argvp[n+1] = (char *)[[cmdArray objectAtIndex:n] cString];
				}
			argvp[n+1] = (char *)0;
	
			chdir([currentDir fileSystemRepresentation]);
	
			execReturnValue = execv(cpath, argvp);
			NSLog(@"Exec return value is %d", execReturnValue);
			exit(127);
			break;

		case -1:
			NSLog(@"*** Error: fork() returned an Error");
			break;

		default:
			NSLog(@"returning to parent process");
			// do nothing ...
		}
	}
#else
	{

	//Use NSTask to lauch the same task on other platforms

	aTask = [[[NSTask alloc] init] autorelease];
	[aTask setCurrentDirectoryPath:currentDir];
	[aTask setLaunchPath:fullExePath];
	[aTask setArguments:cmdArray];
	[aTask launch];
	}
#endif
}