Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

wvfork.cc

Go to the documentation of this file.
00001 /* 00002 * Worldvisions Weaver Software: 00003 * Copyright (C) 1997-2002 Net Integration Technologies, Inc. 00004 * 00005 * wvfork() just runs fork(), but it closes all file descriptors that 00006 * are flagged close-on-exec, since we don't necessarily always run 00007 * exec() after we fork()... 00008 * 00009 * This fixes the year-old mystery bug where WvTapeBackup caused 00010 * watchdog reboots because the CHILD process wasn't touching it, and 00011 * it was already open before the fork()... 00012 * 00013 * If you want to explicitly leave a file descriptor OPEN, even if 00014 * it's marked close-on-exec, then add the fd number to dontclose, and 00015 * pass that to wvfork(). This is mainly useful for WvLoopbacks -- 00016 * you may want certain ones open or closed depending on which call to 00017 * wvfork() you're making. (for WvTapeBackup, you want the three 00018 * backup loopbacks open, and, say, any WvResolver loopbacks closed.) 00019 */ 00020 00021 #include <fcntl.h> 00022 00023 #include "wvfork.h" 00024 #include "wvlinklist.h" 00025 00026 #define MAX_FD sysconf(_SC_OPEN_MAX) + 1 00027 00028 DeclareWvList(WvForkCallback); 00029 WvForkCallbackList callbacks; 00030 00031 00032 void add_wvfork_callback(WvForkCallback cb) 00033 { 00034 #if 0 00035 // be sure we don't add this twice 00036 WvForkCallbackList::Iter i(callbacks); 00037 for (i.rewind(); i.next(); ) 00038 if (*i == cb) return; 00039 #endif 00040 callbacks.append(new WvForkCallback(cb), true); 00041 } 00042 00043 #if 0 00044 void remove_wvfork_callback(WvForkCallback cb) 00045 { 00046 WvForkCallbackList::Iter i(callbacks); 00047 for (i.rewind(); i.next(); ) 00048 if (*i == cb) i.xunlink(); 00049 } 00050 #endif 00051 00052 pid_t wvfork(int dontclose1, int dontclose2) 00053 { 00054 intTable t(1); 00055 if (dontclose1 >= 0) 00056 t.add(&dontclose1, false); 00057 if (dontclose2 >= 0) 00058 t.add(&dontclose2, false); 00059 return (wvfork(t)); 00060 } 00061 00062 pid_t wvfork_start(int *waitfd) 00063 { 00064 int waitpipe[2]; 00065 00066 if (pipe(waitpipe) < 0) 00067 return -1; 00068 00069 pid_t pid = fork(); 00070 00071 WvForkCallbackList::Iter i(callbacks); 00072 for (i.rewind(); i.next(); ) 00073 { 00074 WvForkCallback *cb = i.ptr(); 00075 (*cb)(pid); 00076 } 00077 00078 if (pid < 0) 00079 return pid; 00080 else if (pid > 0) 00081 { 00082 // parent process. close its writing end of the pipe and wait 00083 // for its reading end to close. 00084 char buf; 00085 close(waitpipe[1]); 00086 read(waitpipe[0], &buf, 1); 00087 close(waitpipe[0]); 00088 } 00089 else 00090 { 00091 // child process. close its reading end of the pipe. 00092 close(waitpipe[0]); 00093 *waitfd = waitpipe[1]; 00094 } 00095 00096 return pid; 00097 } 00098 00099 pid_t wvfork(intTable &dontclose) 00100 { 00101 int waitfd = -1; 00102 pid_t pid = wvfork_start(&waitfd); 00103 00104 if (pid != 0) 00105 { 00106 // parent or error 00107 return pid; 00108 } 00109 00110 // child process 00111 // check the close-on-exec flag of all file descriptors 00112 for (int fd = 0; fd < MAX_FD; fd++) 00113 { 00114 if (!dontclose[fd] && fd != waitfd && 00115 (fcntl(fd, F_GETFD) & FD_CLOEXEC) > 0) 00116 close(fd); 00117 } 00118 00119 close(waitfd); 00120 00121 return pid; 00122 }

Generated on Tue Oct 5 01:09:20 2004 for WvStreams by doxygen 1.3.7