def test_fork_chain_child_processes_are_not_orphaned(env: LlvmEnv):
    env.reset("cbench-v1/crc32")

    # Create a chain of forked environments.
    a = env.fork()
    b = a.fork()
    c = b.fork()
    d = c.fork()

    try:
        # Sanity check that they share the same underlying service.
        assert (env.service.connection.process == a.service.connection.process
                == b.service.connection.process == c.service.connection.process
                == d.service.connection.process)
        proc = env.service.connection.process
        # Kill the forked environments one by one.
        a.close()
        assert proc.poll() is None
        b.close()
        assert proc.poll() is None
        c.close()
        assert proc.poll() is None
        d.close()
        assert proc.poll() is None
        # Kill the final environment, refcount 0, service is closed.
        env.close()
        assert proc.poll() is not None
    finally:
        a.close()
        b.close()
        c.close()
        d.close()
def test_fork_child_process_is_not_orphaned(env: LlvmEnv):
    env.reset("cbench-v1/crc32")
    with env.fork() as fkd:
        # Check that both environments share the same service.
        assert isinstance(env.service.connection.process, subprocess.Popen)
        assert isinstance(fkd.service.connection.process, subprocess.Popen)

        assert env.service.connection.process.pid == fkd.service.connection.process.pid
        process = env.service.connection.process

        # Sanity check that both services are alive.
        assert not env.service.connection.process.poll()
        assert not fkd.service.connection.process.poll()

        # Close the parent service.
        env.close()

        # Check that the service is still alive.
        assert not env.service
        assert not fkd.service.connection.process.poll()

        # Close the forked service.
        fkd.close()

        # Check that the service has been killed.
        assert process.poll() is not None
示例#3
0
def test_select_best_action_closed_environment(env: LlvmEnv):
    """Test that select_best_action() recovers from an environment whose service
    has closed."""
    env.reward_space = "IrInstructionCount"
    env.reset(benchmark="cbench-v1/crc32")
    with ThreadPoolExecutor() as executor:
        best_a = select_best_action(env, executor)
        env.close()
        best_b = select_best_action(env, executor)
        assert best_a == best_b
def test_fork_closed_service(env: LlvmEnv):
    env.reset(benchmark="cbench-v1/crc32")

    _, _, done, _ = env.step(0)
    assert not done
    assert env.actions == [0]

    env.close()
    assert not env.service

    with env.fork() as fkd:
        assert env.actions == [0]
        assert fkd.actions == [0]
示例#5
0
def env(request) -> CompilerEnv:
    """Create an LLVM environment."""
    if request.param == "local":
        env = gym.make("llvm-v0")
        env.require_dataset("cBench-v0")
        try:
            yield env
        finally:
            env.close()
    else:
        service = CompilerGymServiceConnection(SERVICE_BIN)
        env = LlvmEnv(service=service.connection.url, benchmark="foo")
        env.require_dataset("cBench-v0")
        try:
            yield env
        finally:
            env.close()
            service.close()
def test_custom_benchmark_is_added_on_service_restart(env: LlvmEnv):
    # When the service is restarted, the environment still uses the same custom
    # benchmark.
    with tempfile.TemporaryDirectory() as d:
        source = Path(d) / "a.c"
        with open(str(source), "w") as f:
            f.write("int main() { return 0; }")

        benchmark = llvm.make_benchmark(source)

    env.reset(benchmark=benchmark)
    assert env.benchmark == benchmark.uri

    # Kill the service so that the next call to reset() starts a new one.
    env.close()
    assert env.service is None

    env.reset()
    assert env.benchmark == benchmark.uri