Example #1
0
File: ruv.py Project: dckc/typhon
def spawn(loop, process, file, args, env, streams):
    """
    The file descriptor list should be a list of streams to wire up to FDs in
    the child. A None stream is mapped to UV_IGNORE.
    """

    with rffi.scoped_str2charp(file) as rawFile:
        rawArgs = rffi.liststr2charpp(args)
        rawEnv = rffi.liststr2charpp(env)
        with rffi.scoped_str2charp(".") as rawCWD:
            options = rffi.make(cConfig["process_options_t"], c_file=rawFile,
                                c_args=rawArgs, c_env=rawEnv, c_cwd=rawCWD)
            with lltype.scoped_alloc(rffi.CArray(stdio_container_t), len(streams)) as rawStreams:
                for i, stream in enumerate(streams):
                    if stream == lltype.nullptr(stream_t):
                        flags = UV_IGNORE
                    else:
                        flags = UV_CREATE_PIPE
                        if i == 0:
                            flags |= UV_READABLE_PIPE
                        elif i in (1, 2):
                            flags |= UV_WRITABLE_PIPE
                        set_stdio_stream(rawStreams[i], stream)
                    rffi.setintfield(rawStreams[i], "c_flags", flags)
                options.c_stdio = rawStreams
                rffi.setintfield(options, "c_stdio_count", len(streams))
                add_exit_cb(options, processDiscard)
                rffi.setintfield(options, "c_flags", UV_PROCESS_WINDOWS_HIDE)
                rv = uv_spawn(loop, process, options)
                free(options)
        rffi.free_charpp(rawEnv)
        rffi.free_charpp(rawArgs)

    check("spawn", rv)
Example #2
0
def spawn(loop, process, file, args, env, streams):
    """
    The file descriptor list should be a list of streams to wire up to FDs in
    the child. A None stream is mapped to UV_IGNORE.
    """

    with rffi.scoped_str2charp(file) as rawFile:
        rawArgs = rffi.liststr2charpp(args)
        rawEnv = rffi.liststr2charpp(env)
        with rffi.scoped_str2charp(".") as rawCWD:
            options = rffi.make(cConfig["process_options_t"], c_file=rawFile,
                                c_args=rawArgs, c_env=rawEnv, c_cwd=rawCWD)
            with lltype.scoped_alloc(rffi.CArray(stdio_container_t),
                                     len(streams)) as rawStreams:
                for i, stream in enumerate(streams):
                    if stream == lltype.nullptr(stream_t):
                        flags = UV_IGNORE
                    else:
                        flags = UV_CREATE_PIPE
                        if i == 0:
                            flags |= UV_READABLE_PIPE
                        elif i in (1, 2):
                            flags |= UV_WRITABLE_PIPE
                        set_stdio_stream(rawStreams[i], stream)
                    rffi.setintfield(rawStreams[i], "c_flags", flags)
                options.c_stdio = rawStreams
                rffi.setintfield(options, "c_stdio_count", len(streams))
                add_exit_cb(options, processDiscard)
                rffi.setintfield(options, "c_flags", UV_PROCESS_WINDOWS_HIDE)
                rv = uv_spawn(loop, process, options)
                free(options)
        rffi.free_charpp(rawEnv)
        rffi.free_charpp(rawArgs)

    check("spawn", rv)
Example #3
0
def spawn(loop, process, file, args, env):
    with rffi.scoped_str2charp(file) as rawFile:
        rawArgs = rffi.liststr2charpp(args)
        rawEnv = rffi.liststr2charpp(env)
        with rffi.scoped_str2charp(".") as rawCWD:
            options = rffi.make(cConfig["process_options_t"], c_file=rawFile,
                                c_args=rawArgs, c_env=rawEnv, c_cwd=rawCWD)
            add_exit_cb(options, processDiscard)
            rffi.setintfield(options, "c_flags", UV_PROCESS_WINDOWS_HIDE)
            rffi.setintfield(options, "c_stdio_count", 0)
            rv = uv_spawn(loop, process, options)
            free(options)
        rffi.free_charpp(rawEnv)
        rffi.free_charpp(rawArgs)

    check("spawn", rv)
Example #4
0
def spawn(loop, process, file, args, env):
    with rffi.scoped_str2charp(file) as rawFile:
        rawArgs = rffi.liststr2charpp(args)
        rawEnv = rffi.liststr2charpp(env)
        with rffi.scoped_str2charp(".") as rawCWD:
            options = rffi.make(cConfig["process_options_t"], c_file=rawFile,
                                c_args=rawArgs, c_env=rawEnv, c_cwd=rawCWD)
            add_exit_cb(options, processDiscard)
            rffi.setintfield(options, "c_flags", UV_PROCESS_WINDOWS_HIDE)
            rffi.setintfield(options, "c_stdio_count", 0)
            rv = uv_spawn(loop, process, options)
            free(options)
        rffi.free_charpp(rawEnv)
        rffi.free_charpp(rawArgs)

    check("spawn", rv)
Example #5
0
def spawn(loop, process, file, args, env, streams):
    """
    The file descriptor list should be a list of streams to wire up to FDs in
    the child. A None stream is mapped to UV_IGNORE.
    """

    with rffi.scoped_str2charp(file) as rawFile:
        rawArgs = rffi.liststr2charpp(args)
        rawEnv = rffi.liststr2charpp(env)
        with rffi.scoped_str2charp(".") as rawCWD:
            options = rffi.make(cConfig["process_options_t"], c_file=rawFile,
                                c_args=rawArgs, c_env=rawEnv, c_cwd=rawCWD)
            with lltype.scoped_alloc(rffi.CArray(stdio_container_t),
                                     len(streams)) as rawStreams:
                for i, stream in enumerate(streams):
                    if stream == lltype.nullptr(stream_t):
                        flags = UV_IGNORE
                    else:
                        flags = UV_CREATE_PIPE
                        if i == 0:
                            flags |= UV_READABLE_PIPE
                        elif i in (1, 2):
                            flags |= UV_WRITABLE_PIPE
                        if not we_are_translated():
                            # doing extra allocations here to work around ll2ctypes'
                            # desire to gratuitously copy arrays
                            with lltype.scoped_alloc(stdio_container_t) as con:
                                set_stdio_stream(con, stream)
                                for field in rawStreams[i]._T._names:
                                    setattr(rawStreams[i], field, getattr(con, field))
                        else:
                            set_stdio_stream(rawStreams[i], stream)
                    rffi.setintfield(rawStreams[i], "c_flags", flags)
                options.c_stdio = rawStreams
                rffi.setintfield(options, "c_stdio_count", len(streams))
                add_exit_cb(options, processDiscard)

                # On Windows, ask to *not* have one of those annoying
                # console/terminal windows pop up. ~ C.
                rffi.setintfield(options, "c_flags", UV_PROCESS_WINDOWS_HIDE)
                rv = uv_spawn(loop, process, options)
                free(options)
        rffi.free_charpp(rawEnv)
        rffi.free_charpp(rawArgs)

    check("spawn", rv)
def fork_exec(space, w_process_args, w_executable_list, w_close_fds,
              w_fds_to_keep, w_cwd, w_env_list, p2cread, p2cwrite, c2pread,
              c2pwrite, errread, errwrite, errpipe_read, errpipe_write,
              restore_signals, call_setsid, w_preexec_fn):
    """\
    fork_exec(args, executable_list, close_fds, cwd, env,
              p2cread, p2cwrite, c2pread, c2pwrite,
              errread, errwrite, errpipe_read, errpipe_write,
              restore_signals, call_setsid, preexec_fn)

    Forks a child process, closes parent file descriptors as appropriate in the
    child and dups the few that are needed before calling exec() in the child
    process.
    
    The preexec_fn, if supplied, will be called immediately before exec.
    WARNING: preexec_fn is NOT SAFE if your application uses threads.
             It may trigger infrequent, difficult to debug deadlocks.
    
    If an error occurs in the child process before the exec, it is
    serialized and written to the errpipe_write fd per subprocess.py.
    
    Returns: the child process's PID.
    
    Raises: Only on an error in the parent process.
    """
    close_fds = space.is_true(w_close_fds)
    if close_fds and errpipe_write < 3:  # precondition
        raise oefmt(space.w_ValueError, "errpipe_write must be >= 3")
    fds_to_keep = build_fd_sequence(space, w_fds_to_keep)

    # No need to disable GC in PyPy:
    # - gc.disable() only disables __del__ anyway.
    # - appelvel __del__ are only called at specific points of the
    #   interpreter.

    l_exec_array = lltype.nullptr(rffi.CCHARPP.TO)
    l_argv = lltype.nullptr(rffi.CCHARPP.TO)
    l_envp = lltype.nullptr(rffi.CCHARPP.TO)
    l_cwd = lltype.nullptr(rffi.CCHARP.TO)
    l_fds_to_keep = lltype.nullptr(rffi.CArrayPtr(rffi.LONG).TO)

    # Convert args and env into appropriate arguments for exec()
    # These conversions are done in the parent process to avoid allocating
    # or freeing memory in the child process.
    try:
        l_exec_array = seqstr2charpp(space, w_executable_list)

        if not space.is_none(w_process_args):
            w_iter = space.iter(w_process_args)
            argv = [
                space.fsencode_w(space.next(w_iter))
                for i in range(space.len_w(w_process_args))
            ]
            l_argv = rffi.liststr2charpp(argv)

        if not space.is_none(w_env_list):
            l_envp = seqstr2charpp(space, w_env_list)

        l_fds_to_keep = lltype.malloc(rffi.CArrayPtr(rffi.LONG).TO,
                                      len(fds_to_keep) + 1,
                                      flavor='raw')
        for i in range(len(fds_to_keep)):
            l_fds_to_keep[i] = fds_to_keep[i]

        if not space.is_none(w_preexec_fn):
            preexec.space = space
            preexec.w_preexec_fn = w_preexec_fn
        else:
            preexec.w_preexec_fn = None

        if not space.is_none(w_cwd):
            cwd = space.fsencode_w(w_cwd)
            l_cwd = rffi.str2charp(cwd)

        run_fork_hooks('before', space)

        try:
            try:
                pid = os.fork()
            except OSError as e:
                raise wrap_oserror(space, e)

            if pid == 0:
                # Child process
                # Code from here to _exit() must only use
                # async-signal-safe functions, listed at `man 7 signal`
                # http://www.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html.
                if not space.is_none(w_preexec_fn):
                    # We'll be calling back into Python later so we need
                    # to do this. This call may not be async-signal-safe
                    # but neither is calling back into Python.  The user
                    # asked us to use hope as a strategy to avoid
                    # deadlock...
                    run_fork_hooks('child', space)

                c_child_exec(l_exec_array, l_argv, l_envp, l_cwd, p2cread,
                             p2cwrite, c2pread, c2pwrite, errread, errwrite,
                             errpipe_read, errpipe_write, close_fds,
                             restore_signals, call_setsid, l_fds_to_keep,
                             len(fds_to_keep), PreexecCallback.run_function,
                             None)
                os._exit(255)
        finally:
            # parent process
            run_fork_hooks('parent', space)

    finally:
        preexec.w_preexec_fn = None

        if l_cwd:
            rffi.free_charp(l_cwd)
        if l_envp:
            rffi.free_charpp(l_envp)
        if l_argv:
            rffi.free_charpp(l_argv)
        if l_exec_array:
            rffi.free_charpp(l_exec_array)
        if l_fds_to_keep:
            lltype.free(l_fds_to_keep, flavor='raw')

    return space.newint(pid)
Example #7
0
def rffi_list_example():
    l = ["Hello", ",", "World", "!"]
    l_charpp = rffi.liststr2charpp(l)
    r = c_strlen_list(l_charpp)
    rffi.free_charpp(l_charpp)
    print r
Example #8
0
                    errread, errwrite, errpipe_read, errpipe_write,
                    close_fds, restore_signals, call_setsid,
                    l_fds_to_keep, len(fds_to_keep),
                    PreexecCallback.run_function, None)
                os._exit(255)
        finally:
            # parent process
            run_fork_hooks('parent', space)

    finally:
        preexec.w_preexec_fn = None

        if l_cwd:
            rffi.free_charp(l_cwd)
        if l_envp:
            rffi.free_charpp(l_envp)
        if l_argv:
            rffi.free_charpp(l_argv)
        if l_exec_array:
            rffi.free_charpp(l_exec_array)
        if l_fds_to_keep:
            lltype.free(l_fds_to_keep, flavor='raw')

    return space.wrap(pid)


def cloexec_pipe(space):
    """cloexec_pipe() -> (read_end, write_end)

    Create a pipe whose ends have the cloexec flag set."""
Example #9
0
                             errpipe_read, errpipe_write, close_fds,
                             restore_signals, call_setsid, l_fds_to_keep,
                             len(fds_to_keep), PreexecCallback.run_function,
                             None)
                os._exit(255)
        finally:
            # parent process
            run_fork_hooks('parent', space)

    finally:
        preexec.w_preexec_fn = None

        if l_cwd:
            rffi.free_charp(l_cwd)
        if l_envp:
            rffi.free_charpp(l_envp)
        if l_argv:
            rffi.free_charpp(l_argv)
        if l_exec_array:
            rffi.free_charpp(l_exec_array)
        if l_fds_to_keep:
            lltype.free(l_fds_to_keep, flavor='raw')

    return space.wrap(pid)


def cloexec_pipe(space):
    """cloexec_pipe() -> (read_end, write_end)

    Create a pipe whose ends have the cloexec flag set."""