We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Compile native op: native signal handler
When running `tools/compile_native_op.py` for example for `NativeLstm2` op, if the output file is specified it now looks like this:
```
/var/tmp/agerstenberger/returnn_native/native_signal_handler/3eb0034669/native_signal_handler.so
/var/tmp/agerstenberger/returnn_tf_cache/ops/NativeLstm2/8c9954fa8e/NativeLstm2.so
/var/tmp/agerstenberger/returnn_tf_cache/ops/GradOfNativeLstm2/d1a9d7605d/GradOfNativeLstm2.so
```

You would not expect to find native_signal_handler.so here. 
Also the `i6_core` job `CompileNativeOpJob` does not check names of the op but just copies the first entry and the second entry as gradient .so., which is now wrong.

So now i'm asking, should we fix it here or do a more robust check in `i6_core`?

A fix here is very simply just moving the line
```python
NativeCodeCompiler.CollectedCompilers = []
```
after the init function is called.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `tools/compile_native_op.py`
Content:
```
1 #!/usr/bin/env python3
2 
3 """
4 This explicitly compiles some of the native ops, and will tell you the so-filenames.
5 Normally all native ops (e.g. NativeLstm2 etc) are compiled on-the-fly within RETURNN.
6 When you export the computation graph (e.g. via ``compile_tf_graph.py``),
7 you explicitly must load these native ops.
8 """
9 
10 from __future__ import annotations
11 
12 import os
13 import sys
14 import typing
15 
16 import _setup_returnn_env  # noqa
17 from returnn import __main__ as rnn
18 from returnn.log import log
19 import argparse
20 import returnn.util.basic as util
21 
22 
23 config = None  # type: typing.Optional["returnn.config.Config"]
24 
25 
26 def init(config_filename, log_verbosity):
27     """
28     :param str config_filename: filename to config-file
29     :param int log_verbosity:
30     """
31     rnn.init_better_exchook()
32     rnn.init_thread_join_hack()
33     if config_filename:
34         print("Using config file %r." % config_filename)
35         assert os.path.exists(config_filename)
36     rnn.init_config(config_filename=config_filename, command_line_options=[])
37     global config
38     config = rnn.config
39     config.set("log", None)
40     config.set("log_verbosity", log_verbosity)
41     config.set("use_tensorflow", True)
42     rnn.init_log()
43     print("Returnn compile-native-op starting up.", file=log.v1)
44     rnn.returnn_greeting()
45     rnn.init_backend_engine()
46     assert util.BackendEngine.is_tensorflow_selected(), "this is only for TensorFlow"
47     rnn.init_faulthandler()
48     if "network" in config.typed_dict:
49         print("Loading network")
50         from returnn.tf.network import TFNetwork
51 
52         network = TFNetwork(name="", config=config, rnd_seed=1, train_flag=False, eval_flag=True, search_flag=False)
53         network.construct_from_dict(config.typed_dict["network"])
54 
55 
56 def main(argv):
57     """
58     Main entry.
59     """
60     from returnn.tf.util.basic import CudaEnv, NativeCodeCompiler
61 
62     CudaEnv.verbose_find_cuda = True
63     NativeCodeCompiler.CollectedCompilers = []
64 
65     argparser = argparse.ArgumentParser(description="Compile some op")
66     argparser.add_argument("--config", help="filename to config-file")
67     argparser.add_argument("--native_op", help="op name. e.g. 'LstmGenericBase'")
68     argparser.add_argument(
69         "--blas_lib", default=None, help="specify which blas lib to use (path to .so or file name to search for)"
70     )
71     argparser.add_argument(
72         "--search_for_numpy_blas",
73         dest="search_for_numpy_blas",
74         action="store_true",
75         help="search for blas inside numpys .libs folder",
76     )
77     argparser.add_argument(
78         "--no_search_for_numpy_blas",
79         dest="search_for_numpy_blas",
80         action="store_false",
81         help="do not search for blas inside numpys .libs folder",
82     )
83     argparser.add_argument("--verbosity", default=4, type=int, help="5 for all seqs (default: 4)")
84     argparser.add_argument("--output_file", help="if given, will write the list of libs to this file")
85     args = argparser.parse_args(argv[1:])
86     init(config_filename=args.config, log_verbosity=args.verbosity)
87 
88     import returnn.native_op as native_op
89     from returnn.tf.native_op import make_op, OpMaker
90 
91     if args.native_op:
92         print("Loading native op %r" % args.native_op)
93         op_gen = getattr(native_op, args.native_op)
94         assert issubclass(op_gen, native_op.NativeOpGenBase)
95         make_op(
96             op_gen,
97             compiler_opts={"verbose": True},
98             search_for_numpy_blas=args.search_for_numpy_blas,
99             blas_lib=args.blas_lib,
100         )
101 
102     libs = []
103     if OpMaker.with_cuda and OpMaker.tf_blas_gemm_workaround:
104         print("CUDA BLAS lib:", OpMaker.cuda_blas_gemm_so_filename())
105         libs.append(OpMaker.cuda_blas_gemm_so_filename())
106     elif OpMaker.with_cuda is False:
107         print("No CUDA.")
108 
109     for compiler in NativeCodeCompiler.CollectedCompilers:
110         assert isinstance(compiler, NativeCodeCompiler)
111         print(compiler)
112         # noinspection PyProtectedMember
113         libs.append(compiler._so_filename)
114 
115     if libs:
116         print("libs:")
117         for fn in libs:
118             print(fn)
119     else:
120         print("no libs compiled. use --native_op or --config")
121 
122     if args.output_file:
123         with open(args.output_file, "w") as f:
124             for fn in libs:
125                 f.write(fn + "\n")
126         print("Wrote lib list to file:", args.output_file)
127 
128 
129 if __name__ == "__main__":
130     main(sys.argv)
131
```
--- 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/tools/compile_native_op.py b/tools/compile_native_op.py
--- a/tools/compile_native_op.py
+++ b/tools/compile_native_op.py
@@ -57,10 +57,10 @@
     """
     Main entry.
     """
-    from returnn.tf.util.basic import CudaEnv, NativeCodeCompiler
+    from returnn.tf.util.basic import CudaEnv, OpCodeCompiler
 
     CudaEnv.verbose_find_cuda = True
-    NativeCodeCompiler.CollectedCompilers = []
+    OpCodeCompiler.CollectedCompilers = []
 
     argparser = argparse.ArgumentParser(description="Compile some op")
     argparser.add_argument("--config", help="filename to config-file")
@@ -106,8 +106,8 @@
     elif OpMaker.with_cuda is False:
         print("No CUDA.")
 
-    for compiler in NativeCodeCompiler.CollectedCompilers:
-        assert isinstance(compiler, NativeCodeCompiler)
+    for compiler in OpCodeCompiler.CollectedCompilers:
+        assert isinstance(compiler, OpCodeCompiler)
         print(compiler)
         # noinspection PyProtectedMember
         libs.append(compiler._so_filename)

{"golden_diff": "diff --git a/tools/compile_native_op.py b/tools/compile_native_op.py\n--- a/tools/compile_native_op.py\n+++ b/tools/compile_native_op.py\n@@ -57,10 +57,10 @@\n     \"\"\"\n     Main entry.\n     \"\"\"\n-    from returnn.tf.util.basic import CudaEnv, NativeCodeCompiler\n+    from returnn.tf.util.basic import CudaEnv, OpCodeCompiler\n \n     CudaEnv.verbose_find_cuda = True\n-    NativeCodeCompiler.CollectedCompilers = []\n+    OpCodeCompiler.CollectedCompilers = []\n \n     argparser = argparse.ArgumentParser(description=\"Compile some op\")\n     argparser.add_argument(\"--config\", help=\"filename to config-file\")\n@@ -106,8 +106,8 @@\n     elif OpMaker.with_cuda is False:\n         print(\"No CUDA.\")\n \n-    for compiler in NativeCodeCompiler.CollectedCompilers:\n-        assert isinstance(compiler, NativeCodeCompiler)\n+    for compiler in OpCodeCompiler.CollectedCompilers:\n+        assert isinstance(compiler, OpCodeCompiler)\n         print(compiler)\n         # noinspection PyProtectedMember\n         libs.append(compiler._so_filename)\n", "issue": "Compile native op: native signal handler\nWhen running `tools/compile_native_op.py` for example for `NativeLstm2` op, if the output file is specified it now looks like this:\r\n```\r\n/var/tmp/agerstenberger/returnn_native/native_signal_handler/3eb0034669/native_signal_handler.so\r\n/var/tmp/agerstenberger/returnn_tf_cache/ops/NativeLstm2/8c9954fa8e/NativeLstm2.so\r\n/var/tmp/agerstenberger/returnn_tf_cache/ops/GradOfNativeLstm2/d1a9d7605d/GradOfNativeLstm2.so\r\n```\r\n\r\nYou would not expect to find native_signal_handler.so here. \r\nAlso the `i6_core` job `CompileNativeOpJob` does not check names of the op but just copies the first entry and the second entry as gradient .so., which is now wrong.\r\n\r\nSo now i'm asking, should we fix it here or do a more robust check in `i6_core`?\r\n\r\nA fix here is very simply just moving the line\r\n```python\r\nNativeCodeCompiler.CollectedCompilers = []\r\n```\r\nafter the init function is called.\n", "before_files": [{"content": "#!/usr/bin/env python3\n\n\"\"\"\nThis explicitly compiles some of the native ops, and will tell you the so-filenames.\nNormally all native ops (e.g. NativeLstm2 etc) are compiled on-the-fly within RETURNN.\nWhen you export the computation graph (e.g. via ``compile_tf_graph.py``),\nyou explicitly must load these native ops.\n\"\"\"\n\nfrom __future__ import annotations\n\nimport os\nimport sys\nimport typing\n\nimport _setup_returnn_env  # noqa\nfrom returnn import __main__ as rnn\nfrom returnn.log import log\nimport argparse\nimport returnn.util.basic as util\n\n\nconfig = None  # type: typing.Optional[\"returnn.config.Config\"]\n\n\ndef init(config_filename, log_verbosity):\n    \"\"\"\n    :param str config_filename: filename to config-file\n    :param int log_verbosity:\n    \"\"\"\n    rnn.init_better_exchook()\n    rnn.init_thread_join_hack()\n    if config_filename:\n        print(\"Using config file %r.\" % config_filename)\n        assert os.path.exists(config_filename)\n    rnn.init_config(config_filename=config_filename, command_line_options=[])\n    global config\n    config = rnn.config\n    config.set(\"log\", None)\n    config.set(\"log_verbosity\", log_verbosity)\n    config.set(\"use_tensorflow\", True)\n    rnn.init_log()\n    print(\"Returnn compile-native-op starting up.\", file=log.v1)\n    rnn.returnn_greeting()\n    rnn.init_backend_engine()\n    assert util.BackendEngine.is_tensorflow_selected(), \"this is only for TensorFlow\"\n    rnn.init_faulthandler()\n    if \"network\" in config.typed_dict:\n        print(\"Loading network\")\n        from returnn.tf.network import TFNetwork\n\n        network = TFNetwork(name=\"\", config=config, rnd_seed=1, train_flag=False, eval_flag=True, search_flag=False)\n        network.construct_from_dict(config.typed_dict[\"network\"])\n\n\ndef main(argv):\n    \"\"\"\n    Main entry.\n    \"\"\"\n    from returnn.tf.util.basic import CudaEnv, NativeCodeCompiler\n\n    CudaEnv.verbose_find_cuda = True\n    NativeCodeCompiler.CollectedCompilers = []\n\n    argparser = argparse.ArgumentParser(description=\"Compile some op\")\n    argparser.add_argument(\"--config\", help=\"filename to config-file\")\n    argparser.add_argument(\"--native_op\", help=\"op name. e.g. 'LstmGenericBase'\")\n    argparser.add_argument(\n        \"--blas_lib\", default=None, help=\"specify which blas lib to use (path to .so or file name to search for)\"\n    )\n    argparser.add_argument(\n        \"--search_for_numpy_blas\",\n        dest=\"search_for_numpy_blas\",\n        action=\"store_true\",\n        help=\"search for blas inside numpys .libs folder\",\n    )\n    argparser.add_argument(\n        \"--no_search_for_numpy_blas\",\n        dest=\"search_for_numpy_blas\",\n        action=\"store_false\",\n        help=\"do not search for blas inside numpys .libs folder\",\n    )\n    argparser.add_argument(\"--verbosity\", default=4, type=int, help=\"5 for all seqs (default: 4)\")\n    argparser.add_argument(\"--output_file\", help=\"if given, will write the list of libs to this file\")\n    args = argparser.parse_args(argv[1:])\n    init(config_filename=args.config, log_verbosity=args.verbosity)\n\n    import returnn.native_op as native_op\n    from returnn.tf.native_op import make_op, OpMaker\n\n    if args.native_op:\n        print(\"Loading native op %r\" % args.native_op)\n        op_gen = getattr(native_op, args.native_op)\n        assert issubclass(op_gen, native_op.NativeOpGenBase)\n        make_op(\n            op_gen,\n            compiler_opts={\"verbose\": True},\n            search_for_numpy_blas=args.search_for_numpy_blas,\n            blas_lib=args.blas_lib,\n        )\n\n    libs = []\n    if OpMaker.with_cuda and OpMaker.tf_blas_gemm_workaround:\n        print(\"CUDA BLAS lib:\", OpMaker.cuda_blas_gemm_so_filename())\n        libs.append(OpMaker.cuda_blas_gemm_so_filename())\n    elif OpMaker.with_cuda is False:\n        print(\"No CUDA.\")\n\n    for compiler in NativeCodeCompiler.CollectedCompilers:\n        assert isinstance(compiler, NativeCodeCompiler)\n        print(compiler)\n        # noinspection PyProtectedMember\n        libs.append(compiler._so_filename)\n\n    if libs:\n        print(\"libs:\")\n        for fn in libs:\n            print(fn)\n    else:\n        print(\"no libs compiled. use --native_op or --config\")\n\n    if args.output_file:\n        with open(args.output_file, \"w\") as f:\n            for fn in libs:\n                f.write(fn + \"\\n\")\n        print(\"Wrote lib list to file:\", args.output_file)\n\n\nif __name__ == \"__main__\":\n    main(sys.argv)\n", "path": "tools/compile_native_op.py"}], "after_files": [{"content": "#!/usr/bin/env python3\n\n\"\"\"\nThis explicitly compiles some of the native ops, and will tell you the so-filenames.\nNormally all native ops (e.g. NativeLstm2 etc) are compiled on-the-fly within RETURNN.\nWhen you export the computation graph (e.g. via ``compile_tf_graph.py``),\nyou explicitly must load these native ops.\n\"\"\"\n\nfrom __future__ import annotations\n\nimport os\nimport sys\nimport typing\n\nimport _setup_returnn_env  # noqa\nfrom returnn import __main__ as rnn\nfrom returnn.log import log\nimport argparse\nimport returnn.util.basic as util\n\n\nconfig = None  # type: typing.Optional[\"returnn.config.Config\"]\n\n\ndef init(config_filename, log_verbosity):\n    \"\"\"\n    :param str config_filename: filename to config-file\n    :param int log_verbosity:\n    \"\"\"\n    rnn.init_better_exchook()\n    rnn.init_thread_join_hack()\n    if config_filename:\n        print(\"Using config file %r.\" % config_filename)\n        assert os.path.exists(config_filename)\n    rnn.init_config(config_filename=config_filename, command_line_options=[])\n    global config\n    config = rnn.config\n    config.set(\"log\", None)\n    config.set(\"log_verbosity\", log_verbosity)\n    config.set(\"use_tensorflow\", True)\n    rnn.init_log()\n    print(\"Returnn compile-native-op starting up.\", file=log.v1)\n    rnn.returnn_greeting()\n    rnn.init_backend_engine()\n    assert util.BackendEngine.is_tensorflow_selected(), \"this is only for TensorFlow\"\n    rnn.init_faulthandler()\n    if \"network\" in config.typed_dict:\n        print(\"Loading network\")\n        from returnn.tf.network import TFNetwork\n\n        network = TFNetwork(name=\"\", config=config, rnd_seed=1, train_flag=False, eval_flag=True, search_flag=False)\n        network.construct_from_dict(config.typed_dict[\"network\"])\n\n\ndef main(argv):\n    \"\"\"\n    Main entry.\n    \"\"\"\n    from returnn.tf.util.basic import CudaEnv, OpCodeCompiler\n\n    CudaEnv.verbose_find_cuda = True\n    OpCodeCompiler.CollectedCompilers = []\n\n    argparser = argparse.ArgumentParser(description=\"Compile some op\")\n    argparser.add_argument(\"--config\", help=\"filename to config-file\")\n    argparser.add_argument(\"--native_op\", help=\"op name. e.g. 'LstmGenericBase'\")\n    argparser.add_argument(\n        \"--blas_lib\", default=None, help=\"specify which blas lib to use (path to .so or file name to search for)\"\n    )\n    argparser.add_argument(\n        \"--search_for_numpy_blas\",\n        dest=\"search_for_numpy_blas\",\n        action=\"store_true\",\n        help=\"search for blas inside numpys .libs folder\",\n    )\n    argparser.add_argument(\n        \"--no_search_for_numpy_blas\",\n        dest=\"search_for_numpy_blas\",\n        action=\"store_false\",\n        help=\"do not search for blas inside numpys .libs folder\",\n    )\n    argparser.add_argument(\"--verbosity\", default=4, type=int, help=\"5 for all seqs (default: 4)\")\n    argparser.add_argument(\"--output_file\", help=\"if given, will write the list of libs to this file\")\n    args = argparser.parse_args(argv[1:])\n    init(config_filename=args.config, log_verbosity=args.verbosity)\n\n    import returnn.native_op as native_op\n    from returnn.tf.native_op import make_op, OpMaker\n\n    if args.native_op:\n        print(\"Loading native op %r\" % args.native_op)\n        op_gen = getattr(native_op, args.native_op)\n        assert issubclass(op_gen, native_op.NativeOpGenBase)\n        make_op(\n            op_gen,\n            compiler_opts={\"verbose\": True},\n            search_for_numpy_blas=args.search_for_numpy_blas,\n            blas_lib=args.blas_lib,\n        )\n\n    libs = []\n    if OpMaker.with_cuda and OpMaker.tf_blas_gemm_workaround:\n        print(\"CUDA BLAS lib:\", OpMaker.cuda_blas_gemm_so_filename())\n        libs.append(OpMaker.cuda_blas_gemm_so_filename())\n    elif OpMaker.with_cuda is False:\n        print(\"No CUDA.\")\n\n    for compiler in OpCodeCompiler.CollectedCompilers:\n        assert isinstance(compiler, OpCodeCompiler)\n        print(compiler)\n        # noinspection PyProtectedMember\n        libs.append(compiler._so_filename)\n\n    if libs:\n        print(\"libs:\")\n        for fn in libs:\n            print(fn)\n    else:\n        print(\"no libs compiled. use --native_op or --config\")\n\n    if args.output_file:\n        with open(args.output_file, \"w\") as f:\n            for fn in libs:\n                f.write(fn + \"\\n\")\n        print(\"Wrote lib list to file:\", args.output_file)\n\n\nif __name__ == \"__main__\":\n    main(sys.argv)\n", "path": "tools/compile_native_op.py"}]}