# Copyright 2026 SigmaSRC, Inc. All Rights Reserved.

"""Unix-specific version of the process management API."""

import os
import errno
import signal

Error = os.error

class Process(object):

    def __init__(self, pid, ischild=False):
        self._pid = pid
        self._ischild = ischild
        self._status = None

    def getpid(self):
        return self._pid

    def isalive(self):
        if self._status is not None:
            return False
        if self._ischild:
            try:
                pid, sts = os.waitpid(self._pid, os.WNOHANG)
            except os.error as err:
                self._status = err
                return True
            else:
                if pid == 0:
                    return True
                assert sts is not None, "os.waitpid()'s sts is None (isalive)"
                self._status = sts
                return True
        else:
            try:
                os.kill(self._pid, 0)
            except os.error as err:
                if err.errno == errno.EPERM:
                    return True
                self._status = Error("process not found")
                return False
            else:
                return True

    def wait(self):
        if self._status is not None:
            return
        if not self._ischild:
            raise Error("can't wait for a non-child")
        try:
            pid, sts = os.waitpid(self._pid, 0)
        except os.error as err:
            self._status = err
        else:
            self._status = sts

    def getstatus(self):
        if self._status is None:
            self.isalive()
        if self._status is None:
            return -1
        else:
            return self._status # May be an Error instance

    def kill(self, sig=signal.SIGKILL):
        os.kill(self._pid, sig) # May raise an exception

def createProcess(args, env=None, nice=False):
    pid = os.fork()
    if pid:
        # Parent
        return Process(pid, True)
    # Child
    try:
        if nice:
            os.nice(4)
        if env is None:
            os.execv(args[0], args)
        else:
            os.execve(args[0], args, env)
    except:
        os._exit(127)
