code: def _poll_process(self):
          
          try:
              self.logger.warning(self.cli_process.stderr.read())
              self.logger.info(self.cli_process.stdout.read())
              return_code = self.cli_process.wait(timeout=0.01)
              if return_code is None:
                  # process is already terminated
                  self.logger.info('Process {0} is terminated'.format(self.process_name))
              else:
                  # process is terminated; possibly by OS
                  self.logger.info('Process {0} got terminated. Cleaning up'.format(self.process_name))
              self.cli_process = None
              return False, return_code
          except TimeoutExpired:
              # process is alive and OK
              return True, None
          except Exception:
              self.logger.error('Exception on polling: {0}'.format(self.process_name), exc_info=True)
              return False, 999
docs: between death of a process and its actual termination lies poorly documented requirement -
              <purging process' io pipes and reading exit status>.
              this can be done either by os.wait() or process.wait()
              :return tuple (boolean: alive, int: return_code)