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 #include <set>
00034 #include "SysUtil.h"
00035 #include "SockUtil.h"
00036 #include "TimeUtil.h"
00037 #include "ScopedLog.h"
00038 #include "Log.h"
00039 #include "maceConfig.h"
00040 #include "m_net.h"
00041 #include <signal.h>
00042
00043 int SysUtil::select(int max, fd_set* rfs, fd_set* wfs, fd_set* efs, uint64_t usec, bool restartOnEINTR) {
00044 if (usec) {
00045 struct timeval tv = { usec / 1000000, usec % 1000000 };
00046 return select(max, rfs, wfs, efs, &tv, restartOnEINTR);
00047 }
00048 else {
00049 return select(max, rfs, wfs, efs, (struct timeval*)0, restartOnEINTR);
00050 }
00051 }
00052
00053 int SysUtil::select(int max, fd_set* rfs, fd_set* wfs, fd_set* efs,
00054 struct timeval* timeout, bool restartOnEINTR) {
00055
00056
00057
00058 int n = 0;
00059 uint64_t sleeptime = 0;
00060 if (timeout) {
00061 sleeptime = TimeUtil::timeu(*timeout);
00062 }
00063
00064 do {
00065 uint64_t start = TimeUtil::timeu();
00066 #if (defined _WINSOCK2_H || defined _WINSOCK_H)
00067 if (max == 0) {
00068 if (sleeptime == 0) {
00069 Sleep(INFINITE);
00070 }
00071 else {
00072 Sleep(sleeptime / 1000);
00073 }
00074 } else {
00075 #endif
00076 n = ::select(max, rfs, wfs, efs, timeout);
00077 #if (defined _WINSOCK2_H || defined _WINSOCK_H)
00078 }
00079 #endif
00080 if (n < 0) {
00081 int err = SockUtil::getErrno();
00082 if (SockUtil::errorInterrupted(err)) {
00083 if (restartOnEINTR) {
00084 if (sleeptime != 0) {
00085 uint64_t now = TimeUtil::timeu();
00086 uint64_t diff = now - start;
00087 if (diff < sleeptime) {
00088 sleeptime -= diff;
00089 TimeUtil::fillTimeval(sleeptime, *timeout);
00090 }
00091 else {
00092
00093 Log::warn() << "WARNING: select was interrupted "
00094 "after it should have timed-out" << Log::end;
00095 return 0;
00096 }
00097 }
00098 } else {
00099 if (rfs) {
00100 FD_ZERO(rfs);
00101 }
00102 if (wfs) {
00103 FD_ZERO(wfs);
00104 }
00105 if (efs) {
00106 FD_ZERO(efs);
00107 }
00108 return 0;
00109 }
00110 }
00111 else if (SockUtil::errorBadF(err)) {
00112 Log::err() << "select returned EBADF" << Log::end;
00113 if (rfs) {
00114 FD_ZERO(rfs);
00115 }
00116 if (wfs) {
00117 FD_ZERO(wfs);
00118 }
00119 if (efs) {
00120 FD_ZERO(efs);
00121 }
00122 return 0;
00123 }
00124 else {
00125 Log::perror("select");
00126 ABORT("select");
00127 }
00128 }
00129 else if (n >= 0) {
00130 return n;
00131 }
00132 } while (true);
00133 }
00134
00135 void SysUtil::sleepu(uint64_t usec) {
00136 sleep(usec / 1000000, usec % 1000000);
00137 }
00138
00139 void SysUtil::sleep(time_t sec, useconds_t usec) {
00140 if (sec > 0 || usec > 0) {
00141 struct timeval tv = { sec, usec };
00142 select(0, 0, 0, 0, &tv);
00143 }
00144 else {
00145 select(0, 0, 0, 0, (struct timeval*)0);
00146 }
00147 }
00148
00149
00150 sighandler_t SysUtil::signal(int signum, sighandler_t handler, bool warn) {
00151 static std::set<int> registeredSignals;
00152
00153 if (registeredSignals.find(signum) != registeredSignals.end()) {
00154 if (warn) {
00155 Log::warn() << "WARNING: signal handler already registered for " << signum
00156 << Log::endl;
00157 }
00158 return handler;
00159 }
00160
00161 registeredSignals.insert(signum);
00162
00163 #ifdef HAVE_SIGACTION
00164 struct sigaction act;
00165 struct sigaction oact;
00166 memset(&act, 0, sizeof(act));
00167 memset(&oact, 0, sizeof(oact));
00168
00169 sigemptyset(&act.sa_mask);
00170 act.sa_flags = SA_RESTART;
00171 act.sa_handler = handler;
00172
00173 assert(sigaction(signum, &act, &oact) == 0);
00174 return oact.sa_handler;
00175 #else
00176 return signal(signum, handler);
00177 #endif
00178 }