We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Is running CompilerGym intended to leave cache directories behind?
## ❓ Questions and Help

Not sure if this is a bug or not, so submitting as a question. Running a CompilerGym experiment leaves behind many cache directories. When running a large experiment, this can create problems through the sheer number of directories in `COMPILER_GYM_CACHE`. I expected the `COMPILER_GYM_CACHE` to not have anything after the experiment exited cleanly.

Is there a way to avoid the experiments leaving the directories behind?

## Steps to reproduce
Running the following on my machine leaves behind about 270 cache directories.

```python
import compiler_gym
import compiler_gym.wrappers
from ray import tune
from ray.rllib.agents.ppo import PPOTrainer


def make_env(env_config):
    env = compiler_gym.make(env_config['cgym_id'])
    env = compiler_gym.wrappers.TimeLimit(env, env_config['timelimit'])
    dataset = env.datasets[env_config['dataset']]
    env = compiler_gym.wrappers.CycleOverBenchmarks(
        env, dataset.benchmarks())
    return env


config = {
    "env_config": {
        "cgym_id": "llvm-autophase-ic-v0",
        "timelimit": 45,
        "dataset": "benchmark://cbench-v1",
    },
    "env": "CompilerGym",
}

stop = {
    "timesteps_total": 10_000,
}

tune.register_env("CompilerGym", make_env)
tune.run(
    PPOTrainer,
    config=config,
    stop=stop,
    name='cgym_cache_dir_demo',
)
```

## Environment

Please fill in this checklist:

- CompilerGym: 0.2.2
- How you installed CompilerGym (conda, pip, source): pip
- OS: Ubuntu 20.04.1 LTS (x86_64)
- Python version: 3.9.7
- Build command you used (if compiling from source): N/A
- GCC/clang version (if compiling from source): N/A
- Bazel version (if compiling from source): N/A
- Versions of any other relevant libraries: ray: 1.10.0, gym: 0.20.0


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `compiler_gym/service/runtime/create_and_run_compiler_gym_service.py`
Content:
```
1 #! /usr/bin/env python3
2 #
3 #  Copyright (c) Facebook, Inc. and its affiliates.
4 #
5 # This source code is licensed under the MIT license found in the
6 # LICENSE file in the root directory of this source tree.
7 """An example CompilerGym service in python."""
8 import os
9 import sys
10 from concurrent import futures
11 from multiprocessing import cpu_count
12 from pathlib import Path
13 from signal import SIGTERM, signal
14 from tempfile import mkdtemp
15 from threading import Event, Thread
16 from typing import Type
17 
18 import grpc
19 from absl import app, flags, logging
20 
21 from compiler_gym.service import connection
22 from compiler_gym.service.compilation_session import CompilationSession
23 from compiler_gym.service.proto import compiler_gym_service_pb2_grpc
24 from compiler_gym.service.runtime.compiler_gym_service import CompilerGymService
25 from compiler_gym.util import debug_util as dbg
26 from compiler_gym.util.filesystem import atomic_file_write
27 from compiler_gym.util.shell_format import plural
28 
29 flags.DEFINE_string("working_dir", "", "Path to use as service working directory")
30 flags.DEFINE_integer("port", 0, "The service listening port")
31 flags.DEFINE_integer(
32     "rpc_service_threads", cpu_count(), "The number of server worker threads"
33 )
34 flags.DEFINE_integer("logbuflevel", 0, "Flag for compatability with C++ service.")
35 FLAGS = flags.FLAGS
36 
37 MAX_MESSAGE_SIZE_IN_BYTES = 512 * 1024 * 1024
38 
39 
40 shutdown_signal = Event()
41 
42 
43 # NOTE(cummins): This script is executed in a subprocess, so code coverage
44 # tracking does not work. As such we use "# pragma: no cover" annotation for all
45 # functions.
46 def _shutdown_handler(signal_number, stack_frame):  # pragma: no cover
47     del stack_frame  # Unused
48     logging.info("Service received signal: %d", signal_number)
49     shutdown_signal.set()
50 
51 
52 def create_and_run_compiler_gym_service(
53     compilation_session_type: Type[CompilationSession],
54 ):  # pragma: no cover
55     """Create and run an RPC service for the given compilation session.
56 
57     This should be called on its own in a self contained script to implement a
58     compilation service. Example:
59 
60     .. code-block:: python
61 
62         from compiler_gym.service import runtime
63         from my_compiler_service import MyCompilationSession
64 
65         if __name__ == "__main__":
66             runtime.create_and_run_compiler_gym_service(MyCompilationSession)
67 
68     This function never returns.
69 
70     :param compilation_session_type: A sublass of :class:`CompilationSession
71         <compiler_gym.service.CompilationSession>` that provides implementations
72         of the abstract methods.
73     """
74 
75     def main(argv):
76         # Register a signal handler for SIGTERM that will set the shutdownSignal
77         # future value.
78         signal(SIGTERM, _shutdown_handler)
79 
80         argv = [x for x in argv if x.strip()]
81         if len(argv) > 1:
82             print(
83                 f"ERROR: Unrecognized command line argument '{argv[1]}'",
84                 file=sys.stderr,
85             )
86             sys.exit(1)
87 
88         working_dir = Path(FLAGS.working_dir or mkdtemp(prefix="compiler_gym-service-"))
89         (working_dir / "logs").mkdir(exist_ok=True, parents=True)
90 
91         FLAGS.log_dir = str(working_dir / "logs")
92         logging.get_absl_handler().use_absl_log_file()
93         logging.set_verbosity(dbg.get_logging_level())
94 
95         # Create the service.
96         server = grpc.server(
97             futures.ThreadPoolExecutor(max_workers=FLAGS.rpc_service_threads),
98             options=connection.GRPC_CHANNEL_OPTIONS,
99         )
100         service = CompilerGymService(
101             working_directory=working_dir,
102             compilation_session_type=compilation_session_type,
103         )
104         compiler_gym_service_pb2_grpc.add_CompilerGymServiceServicer_to_server(
105             service, server
106         )
107 
108         address = f"0.0.0.0:{FLAGS.port}" if FLAGS.port else "0.0.0.0:0"
109         port = server.add_insecure_port(address)
110 
111         with atomic_file_write(working_dir / "port.txt", fileobj=True, mode="w") as f:
112             f.write(str(port))
113 
114         with atomic_file_write(working_dir / "pid.txt", fileobj=True, mode="w") as f:
115             f.write(str(os.getpid()))
116 
117         logging.info(
118             "Service %s listening on %d, PID = %d", working_dir, port, os.getpid()
119         )
120 
121         server.start()
122 
123         # Block on the RPC service in a separate thread. This enables the
124         # current thread to handle the shutdown routine.
125         server_thread = Thread(target=server.wait_for_termination)
126         server_thread.start()
127 
128         # Block until the shutdown signal is received.
129         shutdown_signal.wait()
130         logging.info("Shutting down the RPC service")
131         server.stop(60).wait()
132         server_thread.join()
133 
134         if len(service.sessions):
135             print(
136                 "ERROR: Killing a service with",
137                 plural(len(service.session), "active session", "active sessions"),
138                 file=sys.stderr,
139             )
140             sys.exit(6)
141 
142     app.run(main)
143
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/compiler_gym/service/runtime/create_and_run_compiler_gym_service.py b/compiler_gym/service/runtime/create_and_run_compiler_gym_service.py
--- a/compiler_gym/service/runtime/create_and_run_compiler_gym_service.py
+++ b/compiler_gym/service/runtime/create_and_run_compiler_gym_service.py
@@ -130,6 +130,7 @@
         logging.info("Shutting down the RPC service")
         server.stop(60).wait()
         server_thread.join()
+        logging.info("Service closed")
 
         if len(service.sessions):
             print(

{"golden_diff": "diff --git a/compiler_gym/service/runtime/create_and_run_compiler_gym_service.py b/compiler_gym/service/runtime/create_and_run_compiler_gym_service.py\n--- a/compiler_gym/service/runtime/create_and_run_compiler_gym_service.py\n+++ b/compiler_gym/service/runtime/create_and_run_compiler_gym_service.py\n@@ -130,6 +130,7 @@\n         logging.info(\"Shutting down the RPC service\")\n         server.stop(60).wait()\n         server_thread.join()\n+        logging.info(\"Service closed\")\n \n         if len(service.sessions):\n             print(\n", "issue": "Is running CompilerGym intended to leave cache directories behind?\n## \u2753 Questions and Help\r\n\r\nNot sure if this is a bug or not, so submitting as a question. Running a CompilerGym experiment leaves behind many cache directories. When running a large experiment, this can create problems through the sheer number of directories in `COMPILER_GYM_CACHE`. I expected the `COMPILER_GYM_CACHE` to not have anything after the experiment exited cleanly.\r\n\r\nIs there a way to avoid the experiments leaving the directories behind?\r\n\r\n## Steps to reproduce\r\nRunning the following on my machine leaves behind about 270 cache directories.\r\n\r\n```python\r\nimport compiler_gym\r\nimport compiler_gym.wrappers\r\nfrom ray import tune\r\nfrom ray.rllib.agents.ppo import PPOTrainer\r\n\r\n\r\ndef make_env(env_config):\r\n    env = compiler_gym.make(env_config['cgym_id'])\r\n    env = compiler_gym.wrappers.TimeLimit(env, env_config['timelimit'])\r\n    dataset = env.datasets[env_config['dataset']]\r\n    env = compiler_gym.wrappers.CycleOverBenchmarks(\r\n        env, dataset.benchmarks())\r\n    return env\r\n\r\n\r\nconfig = {\r\n    \"env_config\": {\r\n        \"cgym_id\": \"llvm-autophase-ic-v0\",\r\n        \"timelimit\": 45,\r\n        \"dataset\": \"benchmark://cbench-v1\",\r\n    },\r\n    \"env\": \"CompilerGym\",\r\n}\r\n\r\nstop = {\r\n    \"timesteps_total\": 10_000,\r\n}\r\n\r\ntune.register_env(\"CompilerGym\", make_env)\r\ntune.run(\r\n    PPOTrainer,\r\n    config=config,\r\n    stop=stop,\r\n    name='cgym_cache_dir_demo',\r\n)\r\n```\r\n\r\n## Environment\r\n\r\nPlease fill in this checklist:\r\n\r\n- CompilerGym: 0.2.2\r\n- How you installed CompilerGym (conda, pip, source): pip\r\n- OS: Ubuntu 20.04.1 LTS (x86_64)\r\n- Python version: 3.9.7\r\n- Build command you used (if compiling from source): N/A\r\n- GCC/clang version (if compiling from source): N/A\r\n- Bazel version (if compiling from source): N/A\r\n- Versions of any other relevant libraries: ray: 1.10.0, gym: 0.20.0\r\n\n", "before_files": [{"content": "#! /usr/bin/env python3\n#\n#  Copyright (c) Facebook, Inc. and its affiliates.\n#\n# This source code is licensed under the MIT license found in the\n# LICENSE file in the root directory of this source tree.\n\"\"\"An example CompilerGym service in python.\"\"\"\nimport os\nimport sys\nfrom concurrent import futures\nfrom multiprocessing import cpu_count\nfrom pathlib import Path\nfrom signal import SIGTERM, signal\nfrom tempfile import mkdtemp\nfrom threading import Event, Thread\nfrom typing import Type\n\nimport grpc\nfrom absl import app, flags, logging\n\nfrom compiler_gym.service import connection\nfrom compiler_gym.service.compilation_session import CompilationSession\nfrom compiler_gym.service.proto import compiler_gym_service_pb2_grpc\nfrom compiler_gym.service.runtime.compiler_gym_service import CompilerGymService\nfrom compiler_gym.util import debug_util as dbg\nfrom compiler_gym.util.filesystem import atomic_file_write\nfrom compiler_gym.util.shell_format import plural\n\nflags.DEFINE_string(\"working_dir\", \"\", \"Path to use as service working directory\")\nflags.DEFINE_integer(\"port\", 0, \"The service listening port\")\nflags.DEFINE_integer(\n    \"rpc_service_threads\", cpu_count(), \"The number of server worker threads\"\n)\nflags.DEFINE_integer(\"logbuflevel\", 0, \"Flag for compatability with C++ service.\")\nFLAGS = flags.FLAGS\n\nMAX_MESSAGE_SIZE_IN_BYTES = 512 * 1024 * 1024\n\n\nshutdown_signal = Event()\n\n\n# NOTE(cummins): This script is executed in a subprocess, so code coverage\n# tracking does not work. As such we use \"# pragma: no cover\" annotation for all\n# functions.\ndef _shutdown_handler(signal_number, stack_frame):  # pragma: no cover\n    del stack_frame  # Unused\n    logging.info(\"Service received signal: %d\", signal_number)\n    shutdown_signal.set()\n\n\ndef create_and_run_compiler_gym_service(\n    compilation_session_type: Type[CompilationSession],\n):  # pragma: no cover\n    \"\"\"Create and run an RPC service for the given compilation session.\n\n    This should be called on its own in a self contained script to implement a\n    compilation service. Example:\n\n    .. code-block:: python\n\n        from compiler_gym.service import runtime\n        from my_compiler_service import MyCompilationSession\n\n        if __name__ == \"__main__\":\n            runtime.create_and_run_compiler_gym_service(MyCompilationSession)\n\n    This function never returns.\n\n    :param compilation_session_type: A sublass of :class:`CompilationSession\n        <compiler_gym.service.CompilationSession>` that provides implementations\n        of the abstract methods.\n    \"\"\"\n\n    def main(argv):\n        # Register a signal handler for SIGTERM that will set the shutdownSignal\n        # future value.\n        signal(SIGTERM, _shutdown_handler)\n\n        argv = [x for x in argv if x.strip()]\n        if len(argv) > 1:\n            print(\n                f\"ERROR: Unrecognized command line argument '{argv[1]}'\",\n                file=sys.stderr,\n            )\n            sys.exit(1)\n\n        working_dir = Path(FLAGS.working_dir or mkdtemp(prefix=\"compiler_gym-service-\"))\n        (working_dir / \"logs\").mkdir(exist_ok=True, parents=True)\n\n        FLAGS.log_dir = str(working_dir / \"logs\")\n        logging.get_absl_handler().use_absl_log_file()\n        logging.set_verbosity(dbg.get_logging_level())\n\n        # Create the service.\n        server = grpc.server(\n            futures.ThreadPoolExecutor(max_workers=FLAGS.rpc_service_threads),\n            options=connection.GRPC_CHANNEL_OPTIONS,\n        )\n        service = CompilerGymService(\n            working_directory=working_dir,\n            compilation_session_type=compilation_session_type,\n        )\n        compiler_gym_service_pb2_grpc.add_CompilerGymServiceServicer_to_server(\n            service, server\n        )\n\n        address = f\"0.0.0.0:{FLAGS.port}\" if FLAGS.port else \"0.0.0.0:0\"\n        port = server.add_insecure_port(address)\n\n        with atomic_file_write(working_dir / \"port.txt\", fileobj=True, mode=\"w\") as f:\n            f.write(str(port))\n\n        with atomic_file_write(working_dir / \"pid.txt\", fileobj=True, mode=\"w\") as f:\n            f.write(str(os.getpid()))\n\n        logging.info(\n            \"Service %s listening on %d, PID = %d\", working_dir, port, os.getpid()\n        )\n\n        server.start()\n\n        # Block on the RPC service in a separate thread. This enables the\n        # current thread to handle the shutdown routine.\n        server_thread = Thread(target=server.wait_for_termination)\n        server_thread.start()\n\n        # Block until the shutdown signal is received.\n        shutdown_signal.wait()\n        logging.info(\"Shutting down the RPC service\")\n        server.stop(60).wait()\n        server_thread.join()\n\n        if len(service.sessions):\n            print(\n                \"ERROR: Killing a service with\",\n                plural(len(service.session), \"active session\", \"active sessions\"),\n                file=sys.stderr,\n            )\n            sys.exit(6)\n\n    app.run(main)\n", "path": "compiler_gym/service/runtime/create_and_run_compiler_gym_service.py"}], "after_files": [{"content": "#! /usr/bin/env python3\n#\n#  Copyright (c) Facebook, Inc. and its affiliates.\n#\n# This source code is licensed under the MIT license found in the\n# LICENSE file in the root directory of this source tree.\n\"\"\"An example CompilerGym service in python.\"\"\"\nimport os\nimport sys\nfrom concurrent import futures\nfrom multiprocessing import cpu_count\nfrom pathlib import Path\nfrom signal import SIGTERM, signal\nfrom tempfile import mkdtemp\nfrom threading import Event, Thread\nfrom typing import Type\n\nimport grpc\nfrom absl import app, flags, logging\n\nfrom compiler_gym.service import connection\nfrom compiler_gym.service.compilation_session import CompilationSession\nfrom compiler_gym.service.proto import compiler_gym_service_pb2_grpc\nfrom compiler_gym.service.runtime.compiler_gym_service import CompilerGymService\nfrom compiler_gym.util import debug_util as dbg\nfrom compiler_gym.util.filesystem import atomic_file_write\nfrom compiler_gym.util.shell_format import plural\n\nflags.DEFINE_string(\"working_dir\", \"\", \"Path to use as service working directory\")\nflags.DEFINE_integer(\"port\", 0, \"The service listening port\")\nflags.DEFINE_integer(\n    \"rpc_service_threads\", cpu_count(), \"The number of server worker threads\"\n)\nflags.DEFINE_integer(\"logbuflevel\", 0, \"Flag for compatability with C++ service.\")\nFLAGS = flags.FLAGS\n\nMAX_MESSAGE_SIZE_IN_BYTES = 512 * 1024 * 1024\n\n\nshutdown_signal = Event()\n\n\n# NOTE(cummins): This script is executed in a subprocess, so code coverage\n# tracking does not work. As such we use \"# pragma: no cover\" annotation for all\n# functions.\ndef _shutdown_handler(signal_number, stack_frame):  # pragma: no cover\n    del stack_frame  # Unused\n    logging.info(\"Service received signal: %d\", signal_number)\n    shutdown_signal.set()\n\n\ndef create_and_run_compiler_gym_service(\n    compilation_session_type: Type[CompilationSession],\n):  # pragma: no cover\n    \"\"\"Create and run an RPC service for the given compilation session.\n\n    This should be called on its own in a self contained script to implement a\n    compilation service. Example:\n\n    .. code-block:: python\n\n        from compiler_gym.service import runtime\n        from my_compiler_service import MyCompilationSession\n\n        if __name__ == \"__main__\":\n            runtime.create_and_run_compiler_gym_service(MyCompilationSession)\n\n    This function never returns.\n\n    :param compilation_session_type: A sublass of :class:`CompilationSession\n        <compiler_gym.service.CompilationSession>` that provides implementations\n        of the abstract methods.\n    \"\"\"\n\n    def main(argv):\n        # Register a signal handler for SIGTERM that will set the shutdownSignal\n        # future value.\n        signal(SIGTERM, _shutdown_handler)\n\n        argv = [x for x in argv if x.strip()]\n        if len(argv) > 1:\n            print(\n                f\"ERROR: Unrecognized command line argument '{argv[1]}'\",\n                file=sys.stderr,\n            )\n            sys.exit(1)\n\n        working_dir = Path(FLAGS.working_dir or mkdtemp(prefix=\"compiler_gym-service-\"))\n        (working_dir / \"logs\").mkdir(exist_ok=True, parents=True)\n\n        FLAGS.log_dir = str(working_dir / \"logs\")\n        logging.get_absl_handler().use_absl_log_file()\n        logging.set_verbosity(dbg.get_logging_level())\n\n        # Create the service.\n        server = grpc.server(\n            futures.ThreadPoolExecutor(max_workers=FLAGS.rpc_service_threads),\n            options=connection.GRPC_CHANNEL_OPTIONS,\n        )\n        service = CompilerGymService(\n            working_directory=working_dir,\n            compilation_session_type=compilation_session_type,\n        )\n        compiler_gym_service_pb2_grpc.add_CompilerGymServiceServicer_to_server(\n            service, server\n        )\n\n        address = f\"0.0.0.0:{FLAGS.port}\" if FLAGS.port else \"0.0.0.0:0\"\n        port = server.add_insecure_port(address)\n\n        with atomic_file_write(working_dir / \"port.txt\", fileobj=True, mode=\"w\") as f:\n            f.write(str(port))\n\n        with atomic_file_write(working_dir / \"pid.txt\", fileobj=True, mode=\"w\") as f:\n            f.write(str(os.getpid()))\n\n        logging.info(\n            \"Service %s listening on %d, PID = %d\", working_dir, port, os.getpid()\n        )\n\n        server.start()\n\n        # Block on the RPC service in a separate thread. This enables the\n        # current thread to handle the shutdown routine.\n        server_thread = Thread(target=server.wait_for_termination)\n        server_thread.start()\n\n        # Block until the shutdown signal is received.\n        shutdown_signal.wait()\n        logging.info(\"Shutting down the RPC service\")\n        server.stop(60).wait()\n        server_thread.join()\n        logging.info(\"Service closed\")\n\n        if len(service.sessions):\n            print(\n                \"ERROR: Killing a service with\",\n                plural(len(service.session), \"active session\", \"active sessions\"),\n                file=sys.stderr,\n            )\n            sys.exit(6)\n\n    app.run(main)\n", "path": "compiler_gym/service/runtime/create_and_run_compiler_gym_service.py"}]}