Ejemplo n.º 1
0
    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)
            )
Ejemplo n.º 2
0
    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()