def __init__(self, config, opts, args): self.config = config self.opts = opts self.args = args if not opts.keep_descriptors: _osutil.close_descriptors() if 'pidfile' not in config.wtf: raise ConfigurationError("Missing pidfile configuration") self.pidfile = Pidfile( _os.path.normpath(_os.path.join(config.ROOT, config.wtf.pidfile)) ) if 'detach' not in config.wtf: raise ConfigurationError("Missing detach configuration") self._work = config.wtf.detach and \ DetachedRunner(self).run or Runner(self).run self.mode = _opi.OPIInterface.MODE_THREADED self.errorlog = config.wtf('errorlog') if self.errorlog is not None: self.errorlog = _os.path.normpath( _os.path.join(config.ROOT, self.errorlog) )
def _force_reload(self, accepted): """ Force the application reload and handle the one accepted socket This method forks the process and proxies the socket to the new one. :Parameters: - `accepted`: Accepted socket :Types: - `accepted`: ``tuple`` :Exceptions: - `ReloadRequested`: raised in parent to stop further processing """ # pylint: disable = R0912, R0914, R0915 osock, _ = accepted rfd, wfd = _os.pipe() # need to synchronize if _os.fork() != 0: # parent osock.close() return # child try: try: _os.close(wfd) _os.read(rfd, 1) # wait for EOF (parent died) _os.close(rfd) _osutil.close_descriptors(osock.fileno()) sockname = osock.getsockname() if isinstance(sockname, str): family = _socket.AF_UNIX elif len(sockname) == 2: family = _socket.AF_INET else: family = _socket.AF_INET6 # dup here, to keep the descriptor IDs low. sock = _socket.fromfd( osock.fileno(), family, _socket.SOCK_STREAM ) osock.close() psock = _socket.socket(family, _socket.SOCK_STREAM) psock.settimeout(10) psock.connect(sockname) psock.settimeout(0) sock.settimeout(0) _osutil.disable_nagle(psock) import select as _select rset = [sock.fileno(), psock.fileno()] wset = set() peers = { sock.fileno(): psock.fileno(), psock.fileno(): sock.fileno(), } socks = {sock.fileno(): sock, psock.fileno(): psock} buf = {sock.fileno(): [], psock.fileno(): []} wwait = {} while rset or wset: for fd, flag in wwait.iteritems(): if flag: wset.add(fd) wwait[fd] = (wwait[fd] + 1) % 2 rfds, wfds, _ = _select.select(rset, wset, [], 1) for fd in rfds: sock = socks[fd] try: data = sock.recv(8192) if data: buf[fd].append(data) wset.add(peers[fd]) else: rset.remove(fd) wwait[fd] = 1 sock.shutdown(_socket.SHUT_RD) except _socket.error, e: if e[0] != _errno.EAGAIN: raise for fd in wfds: sock = socks[fd] try: data = ''.join(buf[peers[fd]]) if data: numsent = sock.send(data) data = data[numsent:] else: rset.remove(peers[fd]) socks[peers[fd]].shutdown(_socket.SHUT_RD) if data: buf[peers[fd]] = [data] else: buf[peers[fd]] = [] wset.remove(fd) if peers[fd] not in rset: sock.shutdown(_socket.SHUT_WR) except _socket.error, e: if e[0] != _errno.EAGAIN: raise if len(rset) + len(wset) == 1: if sum(map(len, buf.itervalues())) > 0: continue break for sock in socks.itervalues(): sock.close()