Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F79538133
persist.c
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Tue, Aug 27, 00:28
Size
8 KB
Mime Type
text/x-c
Expires
Thu, Aug 29, 00:28 (2 d)
Engine
blob
Format
Raw Data
Handle
20203311
Attached To
R10977 RADIANCE Photon Map
persist.c
View Options
#ifndef lint
static
const
char
RCSid
[]
=
"$Id: persist.c,v 2.44 2016/03/06 01:13:18 schorsch Exp $"
;
#endif
/*
* Routines for persistent rtrace and rpict processes.
*
* External symbols declared in ray.h
*/
#include "copyright.h"
#include <string.h>
#include <signal.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "platform.h"
#ifndef NON_POSIX
/* XXX need abstraction for process management */
#include <sys/wait.h>
#endif
#include "rtprocess.h"
/* getpid() */
#include "standard.h"
#include "random.h"
#include "ray.h"
#ifdef F_SETLKW
#include "paths.h"
#include "selcall.h"
#ifndef TIMELIM
#define TIMELIM (8*3600)
/* time limit for holding pattern */
#endif
extern
int
headismine
;
/* boolean true if header belongs to me */
extern
char
*
progname
;
/* global program name */
extern
char
*
errfile
;
/* global error file name */
static
char
*
persistfname
=
NULL
;
/* persist file name */
static
int
persistfd
=
-
1
;
/* persist file descriptor */
static
char
inpname
[
TEMPLEN
+
1
],
outpname
[
TEMPLEN
+
1
],
errname
[
TEMPLEN
+
1
];
typedef
void
(
rsighandler_t
)(
int
);
static
rsighandler_t
sig_io
;
static
rsighandler_t
sig_alrm
;
void
pfdetach
(
void
)
/* release persist (and header) resources */
{
if
(
persistfd
>=
0
)
close
(
persistfd
);
persistfd
=
-
1
;
persistfname
=
NULL
;
inpname
[
0
]
=
'\0'
;
outpname
[
0
]
=
'\0'
;
errname
[
0
]
=
'\0'
;
headismine
=
0
;
}
void
pfclean
(
void
)
/* clean up persist files */
{
if
(
persistfd
>=
0
)
close
(
persistfd
);
if
(
persistfname
!=
NULL
)
unlink
(
persistfname
);
if
(
inpname
[
0
])
unlink
(
inpname
);
if
(
outpname
[
0
])
unlink
(
outpname
);
if
(
errname
[
0
])
unlink
(
errname
);
}
void
pflock
(
/* place or release exclusive lock on file */
int
lf
)
{
struct
flock
fls
;
fls
.
l_type
=
lf
?
F_WRLCK
:
F_UNLCK
;
fls
.
l_whence
=
0
;
fls
.
l_start
=
0L
;
fls
.
l_len
=
0L
;
if
(
fcntl
(
persistfd
,
F_SETLKW
,
&
fls
)
<
0
)
error
(
SYSTEM
,
"cannot (un)lock persist file"
);
}
void
persistfile
(
/* open persist file and lock it */
char
*
pfn
)
{
persistfd
=
open
(
pfn
,
O_WRONLY
|
O_CREAT
|
O_EXCL
,
0644
);
if
(
persistfd
>=
0
)
{
persistfname
=
pfn
;
pflock
(
1
);
return
;
}
/* file exists -- switch to i/o process */
persistfd
=
open
(
pfn
,
O_RDWR
);
if
(
persistfd
<
0
)
{
sprintf
(
errmsg
,
"cannot open persist file
\"
%s
\"
"
,
pfn
);
error
(
SYSTEM
,
errmsg
);
}
pflock
(
1
);
io_process
();
/* never returns */
}
static
int
got_io
;
static
void
sig_io
(
int
i
)
{
got_io
++
;
}
static
void
sig_alrm
(
int
i
)
{
quit
(
0
);
}
void
pfhold
(
void
)
/* holding pattern for idle rendering process */
{
rsighandler_t
*
oldalrm
;
char
buf
[
512
];
int
n
;
/* close input and output descriptors */
close
(
0
);
close
(
1
);
if
(
errfile
==
NULL
)
close
(
2
);
/* create named pipes for input and output */
if
(
mkfifo
(
mktemp
(
strcpy
(
inpname
,
TEMPLATE
)),
0600
)
<
0
)
goto
createrr
;
if
(
mkfifo
(
mktemp
(
strcpy
(
outpname
,
TEMPLATE
)),
0600
)
<
0
)
goto
createrr
;
if
(
errfile
==
NULL
&&
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
);
if
(
write
(
persistfd
,
buf
,
n
)
<
n
)
error
(
SYSTEM
,
"error writing persist file"
);
lseek
(
persistfd
,
(
off_t
)
0
,
SEEK_SET
);
/* wait TIMELIM for someone to signal us */
got_io
=
0
;
signal
(
SIGIO
,
sig_io
);
oldalrm
=
signal
(
SIGALRM
,
sig_alrm
);
alarm
(
TIMELIM
);
pflock
(
0
);
/* unlock persist file for attach */
while
(
!
got_io
)
pause
();
/* wait for attach */
alarm
(
0
);
/* turn off alarm */
signal
(
SIGALRM
,
oldalrm
);
signal
(
SIGIO
,
SIG_DFL
);
pflock
(
1
);
/* grab persist file back */
/* someone wants us; reopen stdin and stdout */
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
])
{
close
(
2
);
if
(
open
(
errname
,
O_WRONLY
)
!=
2
)
error
(
INTERNAL
,
"unexpected stderr file number"
);
unlink
(
errname
);
errname
[
0
]
=
'\0'
;
}
unlink
(
inpname
);
inpname
[
0
]
=
'\0'
;
unlink
(
outpname
);
outpname
[
0
]
=
'\0'
;
return
;
createrr:
error
(
SYSTEM
,
"cannot create named pipes in pfhold"
);
}
void
io_process
(
void
)
/* just act as go-between for actual process */
{
char
*
cp
;
int
nr
,
n
;
char
buf
[
BUFSIZ
],
*
pfin
,
*
pfout
,
*
pferr
;
int
pid
,
nfds
;
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
(
3
+
(
3
*
getpid
()
+
random
())
%
13
);
/* wait until ready */
pflock
(
1
);
}
if
(
nr
<
0
)
error
(
SYSTEM
,
"error reading persist file"
);
ftruncate
(
persistfd
,
(
off_t
)
0L
);
/* truncate persist file */
pfdetach
();
/* close & release persist file */
buf
[
nr
]
=
'\0'
;
/* parse what we got */
if
((
cp
=
strchr
(
buf
,
' '
))
==
NULL
)
goto
formerr
;
*
cp
++
=
'\0'
;
if
((
pid
=
atoi
(
cp
))
<=
0
)
goto
formerr
;
if
((
cp
=
strchr
(
cp
,
'\n'
))
==
NULL
)
goto
formerr
;
pfin
=
++
cp
;
if
((
cp
=
strchr
(
cp
,
'\n'
))
==
NULL
)
goto
formerr
;
*
cp
++
=
'\0'
;
pfout
=
cp
;
if
((
cp
=
strchr
(
cp
,
'\n'
))
==
NULL
)
goto
formerr
;
*
cp
++
=
'\0'
;
pferr
=
cp
;
if
((
cp
=
strchr
(
cp
,
'\n'
))
==
NULL
)
goto
formerr
;
*
cp
++
=
'\0'
;
if
(
cp
-
buf
!=
nr
)
goto
formerr
;
if
(
strcmp
(
buf
,
progname
))
{
sprintf
(
errmsg
,
"persist file for %s, not %s"
,
buf
,
progname
);
error
(
USER
,
errmsg
);
}
/* wake up rendering process */
if
(
kill
(
pid
,
SIGIO
)
<
0
)
error
(
SYSTEM
,
"cannot signal rendering process 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
(
;
;
)
{
/* eater loop */
FD_ZERO
(
&
readfds
);
FD_ZERO
(
&
excepfds
);
nfds
=
0
;
if
(
fdout
>=
0
)
{
FD_SET
(
fdout
,
&
readfds
);
FD_SET
(
fdout
,
&
excepfds
);
nfds
=
fdout
+
1
;
}
if
(
fderr
>=
0
)
{
FD_SET
(
fderr
,
&
readfds
);
FD_SET
(
fderr
,
&
excepfds
);
nfds
=
fderr
+
1
;
}
if
(
nfds
==
0
)
break
;
/* all done, exit */
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
)
||
FD_ISSET
(
fderr
,
&
excepfds
)))
{
nr
=
read
(
fderr
,
cp
=
buf
,
sizeof
(
buf
));
if
(
nr
<
0
)
goto
readerr
;
if
(
nr
==
0
)
{
close
(
fderr
);
/* close(2); don't close stderr! */
fderr
=
-
1
;
}
else
{
cp
[
nr
]
=
'\0'
;
/* deduce status if we can */
n
=
strlen
(
progname
);
if
(
!
strncmp
(
cp
,
progname
,
n
)
&&
cp
[
n
++
]
==
':'
&&
cp
[
n
++
]
==
' '
)
{
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
)
||
FD_ISSET
(
fdout
,
&
excepfds
)))
{
nr
=
read
(
fdout
,
cp
=
buf
,
sizeof
(
buf
));
if
(
nr
<
0
)
goto
readerr
;
if
(
nr
==
0
)
{
/* EOF */
close
(
fdout
);
close
(
1
);
fdout
=
-
1
;
}
else
do
{
/* write it all */
if
((
n
=
write
(
1
,
cp
,
nr
))
<=
0
)
goto
writerr
;
cp
+=
n
;
}
while
((
nr
-=
n
)
>
0
);
}
}
kill
(
pid
,
SIGTERM
);
/* no more process to feed, so... */
waitpid
(
pid
,
0
,
0
);
/* wait for feeder process */
_exit
(
status
);
formerr:
error
(
USER
,
"format error in persist file"
);
readerr:
error
(
SYSTEM
,
"read error in io_process"
);
writerr:
error
(
SYSTEM
,
"write error in io_process"
);
}
#else
void
pfclean
(
void
)
{}
#endif
Event Timeline
Log In to Comment