00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <fcntl.h>
00021
00022 #include "wvfork.h"
00023 #include "wvlinklist.h"
00024
00025 #define MAX_FD sysconf(_SC_OPEN_MAX) + 1
00026
00027 DeclareWvList(WvForkCallback);
00028 static WvForkCallbackList *callbacks;
00029
00030 class StupidWvForkDeallocator
00031 {
00032 public:
00033 ~StupidWvForkDeallocator()
00034 { if (callbacks) delete callbacks; }
00035 };
00036
00037 static StupidWvForkDeallocator sfd;
00038
00039
00040
00041
00042
00043 static WvForkCallbackList &get_callbacks()
00044 {
00045 if (!callbacks)
00046 callbacks = new WvForkCallbackList;
00047 return *callbacks;
00048 }
00049
00050
00051 void add_wvfork_callback(WvForkCallback cb)
00052 {
00053 #if 0
00054
00055 WvForkCallbackList::Iter i(get_callbacks());
00056 for (i.rewind(); i.next(); )
00057 if (*i == cb) return;
00058 #endif
00059 get_callbacks().append(new WvForkCallback(cb), true);
00060 }
00061
00062 #if 0
00063 void remove_wvfork_callback(WvForkCallback cb)
00064 {
00065 WvForkCallbackList::Iter i(get_callbacks());
00066 for (i.rewind(); i.next(); )
00067 if (*i == cb) i.xunlink();
00068 }
00069 #endif
00070
00071 pid_t wvfork(int dontclose1, int dontclose2)
00072 {
00073 intTable t(1);
00074 if (dontclose1 >= 0)
00075 t.add(&dontclose1, false);
00076 if (dontclose2 >= 0)
00077 t.add(&dontclose2, false);
00078 return (wvfork(t));
00079 }
00080
00081 pid_t wvfork_start(int *waitfd)
00082 {
00083 int waitpipe[2];
00084
00085 if (pipe(waitpipe) < 0)
00086 return -1;
00087
00088 pid_t pid = fork();
00089
00090 WvForkCallbackList::Iter i(get_callbacks());
00091 for (i.rewind(); i.next(); )
00092 {
00093 WvForkCallback *cb = i.ptr();
00094 (*cb)(pid);
00095 }
00096
00097 if (pid < 0)
00098 return pid;
00099 else if (pid > 0)
00100 {
00101
00102
00103 char buf;
00104 close(waitpipe[1]);
00105 read(waitpipe[0], &buf, 1);
00106 close(waitpipe[0]);
00107 }
00108 else
00109 {
00110
00111 close(waitpipe[0]);
00112 *waitfd = waitpipe[1];
00113 }
00114
00115 return pid;
00116 }
00117
00118 pid_t wvfork(intTable &dontclose)
00119 {
00120 int waitfd = -1;
00121 pid_t pid = wvfork_start(&waitfd);
00122
00123 if (pid != 0)
00124 {
00125
00126 return pid;
00127 }
00128
00129
00130
00131 for (int fd = 0; fd < MAX_FD; fd++)
00132 {
00133 if (!dontclose[fd] && fd != waitfd &&
00134 (fcntl(fd, F_GETFD) & FD_CLOEXEC) > 0)
00135 close(fd);
00136 }
00137
00138 close(waitfd);
00139
00140 return pid;
00141 }