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
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]
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