Esempio n. 1
0
void
ray_popen(			/* open the specified # processes */
	int	nadd
)
{
					/* check if our table has room */
	if (ray_pnprocs + nadd > MAX_NPROCS)
		nadd = MAX_NPROCS - ray_pnprocs;
	if (nadd <= 0)
		return;
	ambsync();			/* load any new ambient values */
	if (shm_boundary == NULL) {	/* first child process? */
		preload_objs();		/* preload auxiliary data */
					/* set shared memory boundary */
		shm_boundary = (char *)malloc(16);
		strcpy(shm_boundary, "SHM_BOUNDARY");
	}
	fflush(NULL);			/* clear pending output */
	samplestep = ray_pnprocs + nadd;
	while (nadd--) {		/* fork each new process */
		int	p0[2], p1[2];
		if (pipe(p0) < 0 || pipe(p1) < 0)
			error(SYSTEM, "cannot create pipe");
		if ((r_proc[ray_pnprocs].pid = fork()) == 0) {
			int	pn;	/* close others' descriptors */
			for (pn = ray_pnprocs; pn--; ) {
				close(r_proc[pn].fd_send);
				close(r_proc[pn].fd_recv);
			}
			close(p0[0]); close(p1[1]);
			close(0);	/* don't share stdin */
					/* following call never returns */
			ray_pchild(p1[0], p0[1]);
		}
		if (r_proc[ray_pnprocs].pid < 0)
			error(SYSTEM, "cannot fork child process");
		close(p1[0]); close(p0[1]);
		if (rand_samp)		/* decorrelate random sequence */
			srandom(random());
		else
			samplendx++;
		/*
		 * Close write stream on exec to avoid multiprocessing deadlock.
		 * No use in read stream without it, so set flag there as well.
		 */
		fcntl(p1[1], F_SETFD, FD_CLOEXEC);
		fcntl(p0[0], F_SETFD, FD_CLOEXEC);
		r_proc[ray_pnprocs].fd_send = p1[1];
		r_proc[ray_pnprocs].fd_recv = p0[0];
		r_proc[ray_pnprocs].npending = 0;
		ray_pnprocs++;
		ray_pnidle++;
	}
}
Esempio n. 2
0
int
main(int  argc, char  *argv[])
{
#define	 check(ol,al)		if (argv[i][ol] || \
				badarg(argc-i-1,argv+i+1,al)) \
				goto badopt
#define	 bool(olen,var)		switch (argv[i][olen]) { \
				case '\0': var = !var; break; \
				case 'y': case 'Y': case 't': case 'T': \
				case '+': case '1': var = 1; break; \
				case 'n': case 'N': case 'f': case 'F': \
				case '-': case '0': var = 0; break; \
				default: goto badopt; }
	char  *err;
	char  *recover = NULL;
	char  *outfile = NULL;
	char  *zfile = NULL;
	int  loadflags = ~IO_FILES;
	int  seqstart = 0;
	int  persist = 0;
	int  duped1 = -1;
	int  rval;
	int  i;
					/* record start time */
	tstart = time((time_t *)NULL);
					/* global program name */
	progname = argv[0] = fixargv0(argv[0]);
					/* option city */
	for (i = 1; i < argc; i++) {
						/* expand arguments */
		while ((rval = expandarg(&argc, &argv, i)) > 0)
			;
		if (rval < 0) {
			sprintf(errmsg, "cannot expand '%s'", argv[i]);
			error(SYSTEM, errmsg);
		}
		if (argv[i] == NULL || argv[i][0] != '-')
			break;			/* break from options */
		if (!strcmp(argv[i], "-version")) {
			puts(VersionID);
			quit(0);
		}
		if (!strcmp(argv[i], "-defaults") ||
				!strcmp(argv[i], "-help")) {
			printdefaults();
			quit(0);
		}
		rval = getrenderopt(argc-i, argv+i);
		if (rval >= 0) {
			i += rval;
			continue;
		}
		rval = getviewopt(&ourview, argc-i, argv+i);
		if (rval >= 0) {
			i += rval;
			continue;
		}
						/* rpict options */
		switch (argv[i][1]) {
		case 'v':				/* view file */
			if (argv[i][2] != 'f')
				goto badopt;
			check(3,"s");
			rval = viewfile(argv[++i], &ourview, NULL);
			if (rval < 0) {
				sprintf(errmsg,
				"cannot open view file \"%s\"",
						argv[i]);
				error(SYSTEM, errmsg);
			} else if (rval == 0) {
				sprintf(errmsg,
					"bad view file \"%s\"",
						argv[i]);
				error(USER, errmsg);
			}
			break;
		case 'p':				/* pixel */
			switch (argv[i][2]) {
			case 's':				/* sample */
				check(3,"i");
				psample = atoi(argv[++i]);
				break;
			case 't':				/* threshold */
				check(3,"f");
				maxdiff = atof(argv[++i]);
				break;
			case 'j':				/* jitter */
				check(3,"f");
				dstrpix = atof(argv[++i]);
				break;
			case 'a':				/* aspect */
				check(3,"f");
				pixaspect = atof(argv[++i]);
				break;
			case 'm':				/* motion */
				check(3,"f");
				mblur = atof(argv[++i]);
				break;
			case 'd':				/* aperture */
				check(3,"f");
				dblur = atof(argv[++i]);
				break;
			default:
				goto badopt;
			}
			break;
		case 'x':				/* x resolution */
			check(2,"i");
			hresolu = atoi(argv[++i]);
			break;
		case 'y':				/* y resolution */
			check(2,"i");
			vresolu = atoi(argv[++i]);
			break;
		case 'S':				/* slave index */
			check(2,"i");
			seqstart = atoi(argv[++i]);
			break;
		case 'o':				/* output file */
			check(2,"s");
			outfile = argv[++i];
			break;
		case 'z':				/* z file */
			check(2,"s");
			zfile = argv[++i];
			break;
		case 'r':				/* recover file */
			if (argv[i][2] == 'o') {		/* +output */
				check(3,"s");
				outfile = argv[i+1];
			} else
				check(2,"s");
			recover = argv[++i];
			break;
		case 't':				/* timer */
			check(2,"i");
			ralrm = atoi(argv[++i]);
			break;
#ifdef  PERSIST
		case 'P':				/* persist file */
			if (argv[i][2] == 'P') {
				check(3,"s");
				persist = PARALLEL;
			} else {
				check(2,"s");
				persist = PERSIST;
			}
			persistfile(argv[++i]);
			break;
#endif
		case 'w':				/* warnings */
			rval = erract[WARNING].pf != NULL;
			bool(2,rval);
			if (rval) erract[WARNING].pf = wputs;
			else erract[WARNING].pf = NULL;
			break;
		case 'e':				/* error file */
			check(2,"s");
			errfile = argv[++i];
			break;
		default:
			goto badopt;
		}
	}
	err = setview(&ourview);	/* set viewing parameters */
	if (err != NULL)
		error(USER, err);
					/* initialize object types */
	initotypes();
					/* initialize urand */
	if (rand_samp) {
		srandom((long)time(0));
		initurand(0);
	} else {
		srandom(0L);
		initurand(2048);
	}
					/* set up signal handling */
	sigdie(SIGINT, "Interrupt");
#ifdef SIGHUP
	sigdie(SIGHUP, "Hangup");
#endif
	sigdie(SIGTERM, "Terminate");
#ifdef SIGPIPE
	sigdie(SIGPIPE, "Broken pipe");
#endif
#ifdef SIGALRM
	sigdie(SIGALRM, "Alarm clock");
#endif
#ifdef	SIGXCPU
	sigdie(SIGXCPU, "CPU limit exceeded");
	sigdie(SIGXFSZ, "File size exceeded");
#endif
					/* open error file */
	if (errfile != NULL) {
		if (freopen(errfile, "a", stderr) == NULL)
			quit(2);
		fprintf(stderr, "**************\n*** PID %5d: ",
				getpid());
		printargs(argc, argv, stderr);
		putc('\n', stderr);
		fflush(stderr);
	}
#ifdef	NICE
	nice(NICE);			/* lower priority */
#endif
					/* get octree */
	if (i == argc)
		octname = NULL;
	else if (i == argc-1)
		octname = argv[i];
	else
		goto badopt;
	if (seqstart > 0 && octname == NULL)
		error(USER, "missing octree argument");
					/* set up output */
#ifdef  PERSIST
	if (persist) {
		if (recover != NULL)
			error(USER, "persist option used with recover file");
		if (seqstart <= 0)
			error(USER, "persist option only for sequences");
		if (outfile == NULL)
		duped1 = dup(fileno(stdout));	/* don't lose our output */
		openheader();
	} else
#endif
	if (outfile != NULL)
		openheader();
#ifdef	_WIN32
	SET_FILE_BINARY(stdout);
	if (octname == NULL)
		SET_FILE_BINARY(stdin);
#endif
	readoct(octname, loadflags, &thescene, NULL);
	nsceneobjs = nobjects;

	if (loadflags & IO_INFO) {	/* print header */
		printargs(i, argv, stdout);
		printf("SOFTWARE= %s\n", VersionID);
	}

	marksources();			/* find and mark sources */

	setambient();			/* initialize ambient calculation */

#ifdef  PERSIST
	if (persist) {
		fflush(stdout);
		if (outfile == NULL) {		/* reconnect stdout */
			dup2(duped1, fileno(stdout));
			close(duped1);
		}
		if (persist == PARALLEL) {	/* multiprocessing */
			preload_objs();		/* preload scene */
			shm_boundary = (char *)malloc(16);
			strcpy(shm_boundary, "SHM_BOUNDARY");
			while ((rval=fork()) == 0) {	/* keep on forkin' */
				pflock(1);
				pfhold();
				tstart = time((time_t *)NULL);
				ambsync();		/* load new values */
			}
			if (rval < 0)
				error(SYSTEM, "cannot fork child for persist function");
			pfdetach();		/* parent will run then exit */
		}
	}
runagain:
	if (persist) {
		if (outfile == NULL)			/* if out to stdout */
			dupheader();			/* send header */
		else					/* if out to file */
			duped1 = dup(fileno(stdout));	/* hang onto pipe */
	}
#endif
					/* batch render picture(s) */
	rpict(seqstart, outfile, zfile, recover);
					/* flush ambient file */
	ambsync();
#ifdef  PERSIST
	if (persist == PERSIST) {	/* first run-through */
		if ((rval=fork()) == 0) {	/* child loops until killed */
			pflock(1);
			persist = PCHILD;
		} else {			/* original process exits */
			if (rval < 0)
				error(SYSTEM, "cannot fork child for persist function");
			pfdetach();		/* parent exits */
		}
	}
	if (persist == PCHILD) {	/* wait for a signal then go again */
		if (outfile != NULL)
			close(duped1);		/* release output handle */
		pfhold();
		tstart = time((time_t *)NULL);	/* reinitialize */
		raynum = nrays = 0;
		goto runagain;
	}
#endif
	quit(0);

badopt:
	sprintf(errmsg, "command line error at '%s'", argv[i]);
	error(USER, errmsg);
	return 1; /* pro forma return */

#undef	check
#undef	bool
}