Пример #1
0
    def process_started_co(self):
        if self._fut_monitor and not self._fut_monitor.cancelled():
            self._fut_monitor.cancel()
            self._fut_monitor = None

        yield from self.do_startup_pause()

        self._fut_monitor = asyncio. async (self._monitor_service())
        self.add_pending(self._fut_monitor)

        if self._ready_event:
            try:
                if not self.process_timeout:
                    raise asyncio.TimeoutError()
                yield from asyncio.wait_for(self._ready_event.wait(),
                                            self.process_timeout)
            except asyncio.TimeoutError:
                self._ready_event = None
                self._notify_timeout()
            else:
                if self._ready_event:
                    self._ready_event = None
                    rc = self.returncode
                    if rc is not None and not rc.normal_exit:
                        if self.ignore_failures:
                            warn(
                                "{0} (ignored) failure on start-up with result '{1}'"
                                .format(self.name, rc))
                        else:
                            raise ChProcessError(
                                "{0} failed with reported error {1}".format(
                                    self.name, rc),
                                resultcode=rc)
Пример #2
0
    def wait_for_pidfile(self):
        """
        If the pidfile option was specified, then wait until we find a valid pidfile,
        and register the new PID.  This is not done automatically, but is implemented
        here as a utility for process types that need it.
        """
        if not self.pidfile:
            return

        self.logdebug("{0} waiting for PID file: {1}".format(
            self.name, self.pidfile))

        pidsleep = 0.02  # work incrementally up to no more than process_timeout
        minsleep = 3
        expires = time() + self.process_timeout
        last_ex = None

        while time() < expires:
            if not self.family.system_alive:
                return
            yield from asyncio.sleep(pidsleep)
            # ramp up until we hit the minsleep ceiling
            pidsleep = min(pidsleep * 2, minsleep)
            try:
                newpid = int(open(self.pidfile, 'r').read().strip())
            except FileNotFoundError:
                continue
            except Exception as ex:
                # Don't raise this immediately.  The service may create the file before writing the PID.
                last_ex = ChProcessError(
                    "{0} found pid file '{1}' but contents did not contain an integer"
                    .format(self.name, self.pidfile),
                    errno=errno.EINVAL)
                continue

            self.pid = newpid
            return

        if last_ex is not None:
            raise last_ex

        raise ChProcessError(
            "{0} did not find pid file '{1}' before {2}sec process_timeout expired"
            .format(self.name, self.pidfile, self.process_timeout),
            errno=errno.ENOENT)
Пример #3
0
 def _notify_timeout(self):
     service = self.service
     message = "notify service '{1}' did not receive ready notification after {2} second(s), {3}".format(
         service.type, service.name, self.process_timeout,
         "proceeding due to 'ignore_failures=True'"
         if service.ignore_failures else
         "terminating due to 'ignore_failures=False'")
     if not service.ignore_failures:
         self.terminate()
     raise ChProcessError(message)
Пример #4
0
 def process_started_co(self):
     result = yield from self.timed_wait(self.process_timeout,
                                         self._exit_timeout)
     if result is not None and not result.normal_exit:
         if self.ignore_failures:
             warn("{0} (ignored) failure on start-up with result '{1}'".
                  format(self.name, result))
         else:
             raise ChProcessError(
                 "{0} failed on start-up with result '{1}'".format(
                     self.name, result),
                 resultcode=result)
Пример #5
0
 def pid(self, newpid):
     if self._pid is not None and newpid is not None and self._pid is not newpid:
         self.logdebug("{0} changing PID to {1} (from {2})", self.name,
                       newpid, self._pid)
         try:
             pgid = os.getpgid(newpid)
         except ProcessLookupError as ex:
             raise ChProcessError(
                 "{0} attempted to attach the process with PID={1} but there is no such process"
                 .format(self.name, newpid),
                 errno=ex.errno)
         self._attach_pid(newpid)
     self._pid = newpid
Пример #6
0
    def do_startup_pause(self):
        """
        Wait a short time just to see if the process errors out immediately.  This avoids a retry loop
        and catches any immediate failures now.  Can be used by process implementations if needed.
        """

        if not self.startup_pause:
            return

        try:
            result = yield from self.timed_wait(self.startup_pause)
        except asyncio.TimeoutError:
            result = None
        if result is not None and not result.normal_exit:
            if self.ignore_failures:
                warn("{0} (ignored) failure on start-up with result '{1}'".
                     format(self.name, result))
            else:
                raise ChProcessError(
                    "{0} failed on start-up with result '{1}'".format(
                        self.name, result),
                    resultcode=result)