prompt: 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()
  
  ```
  
golden_diff: 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)
  
verification_info: {"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"}]}