00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #ifndef _PIPED_SIGNAL_H
00034 #define _PIPED_SIGNAL_H
00035
00036
00037 #include "SockUtil.h"
00038 #include "SysUtil.h"
00039 #include "FileUtil.h"
00040 #include "Log.h"
00041 #include "maceConfig.h"
00042
00043 #ifndef HAVE_PIPE
00044 #include "Util.h"
00045 #include "Exception.h"
00046 #include "ThreadCreate.h"
00047 #include "NumberGen.h"
00048 #include "m_net.h"
00049 #endif
00050
00105 class PipedSignal
00106 #ifdef HAVE_PIPE
00107 {
00108 #else
00109 : public RunThreadClass {
00110 friend void _runNewThread(pthread_t* t, func f, void* arg,
00111 pthread_attr_t* attr, const char* fname, bool joinThread);
00112 friend void _runNewThreadClass(pthread_t* t, RunThreadClass* c, classfunc f,
00113 void* arg, pthread_attr_t* attr,
00114 const char* fname, bool joinThread);
00115 friend void* connectSignal(void* vfa);
00116 private:
00117 int16_t port;
00118
00119 void* connectSignal(void* arg) {
00120 w = ::socket(AF_INET, SOCK_STREAM, 0);
00121 ASSERT(w >= 0);
00122 struct sockaddr_in sa;
00123 uint32_t bindaddr = ntohl(INADDR_LOOPBACK);
00124 SockUtil::fillSockAddr(bindaddr, port, sa);
00125 if (::connect(w, (struct sockaddr*)&sa, sizeof(sa)) < 0) {
00126 Log::perror("connect");
00127 ABORT("connect");
00128 }
00129 return NULL;
00130 }
00131 #endif
00132
00133 public:
00134 PipedSignal() {
00135 #ifdef HAVE_PIPE
00136 int des[2];
00137 if(pipe(des) < 0) {
00138 Log::perror("pipe");
00139 ASSERT(0);
00140 }
00141 r = des[0];
00142 w = des[1];
00143 #else
00144 SockUtil::init();
00145 socket_t sv = socket(AF_INET, SOCK_STREAM, 0);
00146 if (sv < 0) {
00147 Log::perror("socket");
00148 ABORT("socket");
00149 }
00150
00151 int n = 1;
00152 if (setsockopt(sv, SOL_SOCKET, SO_REUSEADDR, (char*)&n, sizeof(n)) < 0) {
00153 Log::perror("setsockopt");
00154 ABORT("setsockopt");
00155 }
00156
00157 struct sockaddr_in sa;
00158 uint32_t bindaddr = ntohl(INADDR_LOOPBACK);
00159 ASSERT(params::containsKey("PIPED_SIGNAL_SOCKET_PORT"));
00160 port = NumberGen::Instance("PIPED_SIGNAL_SOCKET_PORT")->GetVal();
00161 SockUtil::fillSockAddr(bindaddr, port, sa);
00162
00163 if (bind(sv, (struct sockaddr*)&sa, sizeof(sa)) < 0) {
00164 Log::perror("bind");
00165 ::close(sv);
00166 }
00167 if (listen(sv, 1) < 0) {
00168 Log::perror("listen");
00169 ABORT("listen");
00170 }
00171
00172 sockaddr_in sin;
00173 socklen_t sinlen = sizeof(sin);
00174 memset(&sin, 0, sinlen);
00175 pthread_t pt;
00176 _runNewThreadClass(&pt, this, (classfunc)&PipedSignal::connectSignal, 0, 0, "PipedSignal::constructor", false);
00177 r = ::accept(sv, (struct sockaddr*)&sin, &sinlen);
00178 ASSERT(r > 0);
00179 pthread_join(pt, NULL);
00180 ::close(sv);
00181
00182 #endif
00183 SockUtil::setNonblock(r);
00184 SockUtil::setNonblock(w);
00185 FD_ZERO(&rset);
00186 }
00187
00188 virtual ~PipedSignal() {
00189 close();
00190 }
00191
00193 void addToSet(fd_set& s, socket_t& selectMax) const {
00194
00195 FD_SET(r, &s);
00196 selectMax = std::max(selectMax, r);
00197 }
00198
00200 bool clear(fd_set& s) {
00201 bool ret = FD_ISSET(r, &s);
00202 if (ret) {
00203 read(s);
00204 }
00205 FD_CLR(r, &s);
00206 return ret;
00207 }
00208
00210
00215 void signal() {
00216 #ifdef HAVE_PIPE
00217 if (::write(w, " ", 1) < 0) {
00218 if (!SockUtil::errorWouldBlock()) {
00219 Log::perror("PipedSignal::signal");
00220 }
00221 }
00222 #else
00223 ::send(w, " ", 1, 0);
00224 #endif
00225 }
00226
00228 int wait(uint64_t usec = 0) {
00229
00230 FD_SET(r, &rset);
00231 int n = SysUtil::select(r + 1, &rset, 0, 0, usec);
00232 if (n) {
00233 read(rset);
00234 }
00235
00236 return n;
00237 }
00238
00240 void close() {
00241 ::close(r);
00242 ::close(w);
00243 }
00244
00245 private:
00246 inline void read(fd_set& rs) {
00247 #ifdef HAVE_PIPE
00248 ASSERT(FD_ISSET(r, &rs));
00249 FileUtil::read(r);
00250 #else
00251 int ret = 0;
00252 char buf[1024];
00253 do {
00254 ret = ::recv(r, buf, 1024, 0);
00255 } while (ret > 0);
00256 #endif
00257 }
00258
00259 private:
00260 socket_t r;
00261 socket_t w;
00262 fd_set rset;
00263 };
00264
00265 #if 0
00266
00267
00268 #include "ScopedLock.h"
00269 #include "TimeUtil.h"
00270
00271 class PipedSignal {
00272 public:
00273 PipedSignal() : waiting(false), signalled(false), mutex(PTHREAD_MUTEX_INITIALIZER), cond(PTHREAD_COND_INITIALIZER) {
00274
00275 }
00276
00277 virtual ~PipedSignal() {
00278 }
00279
00280 void signal() {
00281 ScopedLock sl(mutex);
00282 if (!signalled) {
00283 signalled = true;
00284 if (waiting) {
00285 pthread_cond_signal(&cond);
00286 }
00287 }
00288 }
00289
00290 int wait(uint64_t usec = 0) {
00291 struct timeval t;
00292 struct timespec ts;
00293 uint64_t fintime = TimeUtil::timeu() + usec;
00294 TimeUtil::fillTimeval(fintime, t);
00295 ts.tv_sec = t.tv_sec;
00296 ts.tv_nsec = t.tv_usec * 1000;
00297 ScopedLock sl(mutex);
00298 if (!signalled ) {
00299 waiting = true;
00300 pthread_cond_timedwait(&cond, &mutex, &ts);
00301 }
00302 waiting = false;
00303 signalled = false;
00304 return 0;
00305 }
00306
00307 private:
00308 bool waiting;
00309 bool signalled;
00310 pthread_mutex_t mutex;
00311 pthread_cond_t cond;
00312 };
00313
00314
00315 #endif
00316
00317 #endif // _PIPED_SIGNAL_H