--- ray/src/rt/persist.c 1996/07/19 10:16:00 2.17
+++ ray/src/rt/persist.c 2003/02/22 02:07:29 2.26
@@ -1,41 +1,88 @@
-/* Copyright (c) 1996 Regents of the University of California */
-
#ifndef lint
-static char SCCSid[] = "$SunId$ LBL";
+static const char RCSid[] = "$Id: persist.c,v 2.26 2003/02/22 02:07:29 greg Exp $";
#endif
-
/*
* Routines for persistent rtrace and rpict processes.
+ *
+ * External symbols declared in ray.h
*/
+/* ====================================================================
+ * The Radiance Software License, Version 1.0
+ *
+ * Copyright (c) 1990 - 2002 The Regents of the University of California,
+ * through Lawrence Berkeley National Laboratory. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowledgment:
+ * "This product includes Radiance software
+ * (http://radsite.lbl.gov/)
+ * developed by the Lawrence Berkeley National Laboratory
+ * (http://www.lbl.gov/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Radiance," "Lawrence Berkeley National Laboratory"
+ * and "The Regents of the University of California" must
+ * not be used to endorse or promote products derived from this
+ * software without prior written permission. For written
+ * permission, please contact radiance@radsite.lbl.gov.
+ *
+ * 5. Products derived from this software may not be called "Radiance",
+ * nor may "Radiance" appear in their name, without prior written
+ * permission of Lawrence Berkeley National Laboratory.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Lawrence Berkeley National Laboratory OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of Lawrence Berkeley National Laboratory. For more
+ * information on Lawrence Berkeley National Laboratory, please see
+ * .
+ */
+
#include "standard.h"
+#include "random.h"
#ifdef F_SETLKW
#include "paths.h"
+#include "selcall.h"
#include
-#include
#include
- /* select call compatibility stuff */
-#ifndef FD_SETSIZE
-#include
-#define FD_SETSIZE NOFILE /* maximum # select file descriptors */
-#endif
-#ifndef FD_SET
-#ifndef NFDBITS
-#define NFDBITS (8*sizeof(int)) /* number of bits per fd_mask */
-#endif
-#define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
-#define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
-#define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
-#define FD_ZERO(p) bzero((char *)(p), sizeof(*(p)))
-#endif
#ifndef TIMELIM
#define TIMELIM (8*3600) /* time limit for holding pattern */
#endif
-extern char *strcpy(), *index();
+#ifndef freebsd
+#define mkfifo(fn,md) mknod(fn, S_IFIFO|(md), 0)
+#endif
+extern void io_process();
+
extern int headismine; /* boolean true if header belongs to me */
extern char *progname; /* global program name */
@@ -48,6 +95,7 @@ static int persistfd = -1; /* persist file descriptor
static char inpname[TEMPLEN+1], outpname[TEMPLEN+1], errname[TEMPLEN+1];
+void
pfdetach() /* release persist (and header) resources */
{
if (persistfd >= 0)
@@ -61,6 +109,7 @@ pfdetach() /* release persist (and header) resources
}
+void
pfclean() /* clean up persist files */
{
if (persistfd >= 0)
@@ -76,6 +125,7 @@ pfclean() /* clean up persist files */
}
+void
pflock(lf) /* place or release exclusive lock on file */
int lf;
{
@@ -112,14 +162,15 @@ char *pfn;
static int got_io;
-static int sig_io() { got_io++; }
+static void sig_io() { got_io++; }
-static int sig_alrm() { quit(0); }
+static void sig_alrm() { quit(0); }
+void
pfhold() /* holding pattern for idle rendering process */
{
- int (*oldalrm)();
+ void (*oldalrm)();
char buf[512];
register int n;
/* close input and output descriptors */
@@ -128,23 +179,23 @@ pfhold() /* holding pattern for idle rendering proces
if (errfile == NULL)
close(fileno(stderr));
/* create named pipes for input and output */
- if (mknod(mktemp(strcpy(inpname,TEMPLATE)), S_IFIFO|0600, 0) < 0)
+ if (mkfifo(mktemp(strcpy(inpname,TEMPLATE)), 0600) < 0)
goto createrr;
- if (mknod(mktemp(strcpy(outpname,TEMPLATE)), S_IFIFO|0600, 0) < 0)
+ if (mkfifo(mktemp(strcpy(outpname,TEMPLATE)), 0600) < 0)
goto createrr;
if (errfile == NULL &&
- mknod(mktemp(strcpy(errname,TEMPLATE)), S_IFIFO|0600, 0) < 0)
+ mkfifo(mktemp(strcpy(errname,TEMPLATE)), 0600) < 0)
goto createrr;
sprintf(buf, "%s %d\n%s\n%s\n%s\n", progname, getpid(),
inpname, outpname, errname);
n = strlen(buf);
- lseek(persistfd, 0L, 0);
if (write(persistfd, buf, n) < n)
error(SYSTEM, "error writing persist file");
+ lseek(persistfd, (off_t)0L, 0);
/* wait TIMELIM for someone to signal us */
got_io = 0;
signal(SIGIO, sig_io);
- oldalrm = (int (*)())signal(SIGALRM, sig_alrm);
+ oldalrm = (void (*)())signal(SIGALRM, sig_alrm);
alarm(TIMELIM);
pflock(0); /* unlock persist file for attach */
while (!got_io)
@@ -154,13 +205,24 @@ pfhold() /* holding pattern for idle rendering proces
signal(SIGIO, SIG_DFL);
pflock(1); /* grab persist file back */
/* someone wants us; reopen stdin and stdout */
+ /*
if (freopen(inpname, "r", stdin) == NULL)
goto openerr;
if (freopen(outpname, "w", stdout) == NULL)
goto openerr;
+ */
+ close(0);
+ if (open(inpname, O_RDONLY) != 0)
+ error(INTERNAL, "unexpected stdin file number");
+ clearerr(stdin);
+ close(1);
+ if (open(outpname, O_WRONLY) != 1)
+ error(INTERNAL, "unexpected stdout file number");
+ sleep(3); /* give them a chance to open their pipes */
if (errname[0]) {
- if (freopen(errname, "w", stderr) == NULL)
- goto openerr;
+ close(2);
+ if (open(errname, O_WRONLY) != 2)
+ error(INTERNAL, "unexpected stderr file number");
unlink(errname);
errname[0] = '\0';
}
@@ -176,26 +238,28 @@ openerr:
}
+void
io_process() /* just act as go-between for actual process */
{
register char *cp;
register int nr, n;
char buf[BUFSIZ], *pfin, *pfout, *pferr;
int pid, nfds;
- int fdin, fdout, fderr = -1;
- fd_set readfds, writefds, excepfds;
+ int fdout, fderr = -1;
+ int status = 0;
+ fd_set readfds, excepfds;
/* load persist file */
n = 40;
while ((nr = read(persistfd, buf, sizeof(buf)-1)) == 0) {
if (!n--)
error(USER, "unattended persist file?");
pflock(0);
- sleep(15); /* wait until ready */
+ sleep(3+(3*getpid()+random())%13); /* wait until ready */
pflock(1);
}
if (nr < 0)
error(SYSTEM, "error reading persist file");
- ftruncate(persistfd, 0L); /* truncate persist file */
+ ftruncate(persistfd, (off_t)0L); /* truncate persist file */
pfdetach(); /* close & release persist file */
buf[nr] = '\0'; /* parse what we got */
if ((cp = index(buf, ' ')) == NULL)
@@ -226,23 +290,37 @@ io_process() /* just act as go-between for actual pro
/* wake up rendering process */
if (kill(pid, SIGIO) < 0)
error(SYSTEM, "cannot signal rendering process in io_process");
- /* open named pipes, in order */
- if ((fdin = open(pfin, O_WRONLY)) < 0)
- error(SYSTEM, "cannot open input pipe in io_process");
+ /* fork child feeder process */
+ pid = fork();
+ if (pid < 0)
+ error(SYSTEM, "fork failed in io_process");
+ if (pid == 0) { /* feeder loop */
+ int fdin;
+ close(1); /* open input pipe */
+ if ((fdin = open(pfin, O_WRONLY)) < 0)
+ error(SYSTEM, "cannot open feed pipe in io_process");
+ /* renderer stdin */
+ while ((nr = read(0, cp=buf, sizeof(buf))) > 0) {
+ do {
+ if ((n = write(fdin, cp, nr)) <= 0)
+ goto writerr;
+ cp += n;
+ } while ((nr -= n) > 0);
+ }
+ if (nr < 0)
+ goto readerr;
+ _exit(0);
+ }
+ close(0);
+ /* open output pipes, in order */
if ((fdout = open(pfout, O_RDONLY)) < 0)
error(SYSTEM, "cannot open output pipe in io_process");
if (pferr[0] && (fderr = open(pferr, O_RDONLY)) < 0)
error(SYSTEM, "cannot open error pipe in io_process");
- for ( ; ; ) { /* loop on select call */
+ for ( ; ; ) { /* eater loop */
FD_ZERO(&readfds);
- FD_ZERO(&writefds);
FD_ZERO(&excepfds);
nfds = 0;
- if (fdin >= 0) {
- FD_SET(fdin, &writefds);
- FD_SET(fdin, &excepfds);
- nfds = fdin+1;
- }
if (fdout >= 0) {
FD_SET(fdout, &readfds);
FD_SET(fdout, &excepfds);
@@ -255,7 +333,7 @@ io_process() /* just act as go-between for actual pro
}
if (nfds == 0)
break; /* all done, exit */
- if (select(nfds, &readfds, &writefds, &excepfds, NULL) < 0)
+ if (select(nfds, &readfds, NULL, &excepfds, NULL) < 0)
error(SYSTEM, "error in select call in io_process");
/* renderer stderr */
if (fderr >= 0 && (FD_ISSET(fderr, &readfds) ||
@@ -265,14 +343,30 @@ io_process() /* just act as go-between for actual pro
goto readerr;
if (nr == 0) {
close(fderr);
- close(2);
+ /* close(2); don't close stderr! */
fderr = -1;
- } else
- do { /* write it all */
+ } else {
+ cp[nr] = '\0'; /* deduce status if we can */
+ n = strlen(progname);
+ if (!strncmp(cp, progname, n) &&
+ cp[n++] == ':' &&
+ cp[n++] == ' ') {
+ register struct erract *ep;
+ for (ep = erract; ep < erract+NERRS;
+ ep++)
+ if (ep->pre[0] &&
+ !strncmp(cp+n, ep->pre,
+ strlen(ep->pre))) {
+ status = ep->ec;
+ break;
+ }
+ }
+ do { /* write message */
if ((n = write(2, cp, nr)) <= 0)
goto writerr;
cp += n;
} while ((nr -= n) > 0);
+ }
}
/* renderer stdout */
if (fdout >= 0 && (FD_ISSET(fdout, &readfds) ||
@@ -291,21 +385,9 @@ io_process() /* just act as go-between for actual pro
cp += n;
} while ((nr -= n) > 0);
}
- /* renderer stdin */
- if (fdin >= 0 && (FD_ISSET(fdin, &writefds) ||
- FD_ISSET(fdin, &excepfds))) {
- nr = read(0, buf, 512); /* use minimal buffer */
- if (nr < 0)
- goto readerr;
- if (nr == 0) {
- close(0);
- close(fdin);
- fdin = -1;
- } else if (write(fdin, buf, nr) < nr)
- goto writerr; /* what else to do? */
- }
}
- _exit(0); /* we ought to return renderer error status! */
+ wait(0); /* wait for feeder process */
+ _exit(status);
formerr:
error(USER, "format error in persist file");
readerr:
@@ -316,6 +398,6 @@ writerr:
#else
-pfclean() {}
+void pfclean() {}
#endif