We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
pyi_rth_pkgutil.py hook might not work under MacOS in onefile mode
## Description of the issue
I'm using `iter_modules` in our cross-platform OpenSource Project [Specter-Desktop](https://github.com/cryptoadvance/specter-desktop) ([spec-file](https://github.com/cryptoadvance/specter-desktop/blob/master/pyinstaller/specterd.spec)).

For that, the [pyi_rth_pkgutil.py-hook](https://github.com/pyinstaller/pyinstaller/blob/v4.8/PyInstaller/hooks/rthooks/pyi_rth_pkgutil.py) is quite useful and solved my issue on the linux-platform. However, i have an issue with the MacOS-build at runtime:
```
$  ./dist/specterd server --config=DevelopmentConfig
Initializing HWI...
[2022-01-24 11:49:07,827] INFO in server: Configuration: cryptoadvance.specter.config.DevelopmentConfig
[2022-01-24 11:49:07,828] INFO in specter_migrator: Initiated MigDataManager(/Users/thomasmuller/.specter_dev/migration_data.json events:3 execs:2 )
Traceback (most recent call last):
  File "specterd.py", line 4, in <module>
    entry_point()
  File "click/core.py", line 829, in __call__
  File "click/core.py", line 782, in main
  File "click/core.py", line 1259, in invoke
  File "click/core.py", line 1066, in invoke
  File "click/core.py", line 610, in invoke
  File "cryptoadvance/specter/cli/cli_server.py", line 114, in server
  File "cryptoadvance/specter/server.py", line 104, in init_app
  File "cryptoadvance/specter/util/specter_migrator.py", line 125, in execute_migrations
  File "cryptoadvance/specter/util/specter_migrator.py", line 107, in plan_migration
  File "cryptoadvance/specter/util/specter_migrator.py", line 161, in get_migration_classes
  File "PyInstaller/hooks/rthooks/pyi_rth_pkgutil.py", line 59, in _pyi_pkgutil_iter_modules
AssertionError
[20771] Failed to execute script 'specterd' due to unhandled exception!
(.env) thomasmuller @ Thomass-Air.fritz.box ➜  pyinstaller git:(service_swan) ✗
```

So the relevant code is this:
```
        SYS_PREFIX = sys._MEIPASS + os.path.sep
        SYS_PREFIXLEN = len(SYS_PREFIX)
        # Only single path is supported, and it must start with sys._MEIPASS.
        pkg_path = os.path.normpath(path[0])
        assert pkg_path.startswith(SYS_PREFIX)
```
So i inserted some debugging code and figured out that:

```
SYS_PREFIX: /var/folders/bd/k__jfmz112sb1_dyz4rxwfzh0000gn/T/
pkg_path: /private/var/folders/bd/k__jfmz112sb1_dyz4rxwfzh0000gn/T/_MEIBqFxGW/cryptoadvance/specter/util/migrations
```
So in combination with the comment above, it seems that MacOS is using "multiple path" and so MacOS is not supported here?
On the other hand, this [link](https://difyel.com/apple/macos/macos-directory-structure/#Other_directories) is claiming that `private/var` is only a symlink to `/var`. So i added this and this seem to have solved it?
```
        if pkg_path.startswith("/private"):
                pkg_path = pkg_path[8:]
        assert pkg_path.startswith(SYS_PREFIX)
```
Is this a valid fix? I might  make a PR if someone can give me some guidance on this.

### Context information (for bug reports)

* Output of `pyinstaller --version`: ```4.8```
* Version of Python: <!-- e.g. 3.9.7 -->
* Platform: OS X
* How you installed Python: brew
* Did you also try this on another platform? Does it work there? --> Yes, works on Linux



--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `PyInstaller/hooks/rthooks/pyi_rth_pkgutil.py`
Content:
```
1 #-----------------------------------------------------------------------------
2 # Copyright (c) 2021, PyInstaller Development Team.
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 #
7 # The full license is in the file COPYING.txt, distributed with this software.
8 #
9 # SPDX-License-Identifier: Apache-2.0
10 #-----------------------------------------------------------------------------
11 #
12 # This rthook overrides pkgutil.iter_modules with custom implementation that uses PyInstaller's FrozenImporter to list
13 # sub-modules embedded in the PYZ archive. The non-embedded modules (binary extensions, or .pyc modules in noarchive
14 # build) are handled by original pkgutil iter_modules implementation (and consequently, python's FileFinder).
15 #
16 # The preferred way of adding support for iter_modules would be adding non-standard iter_modules() method to
17 # FrozenImporter itself. However, that seems to work only for path entry finders (for use with sys.path_hooks), while
18 # PyInstaller's FrozenImporter is registered as meta path finders (for use with sys.meta_path). Turning FrozenImporter
19 # into path entry finder, would seemingly require the latter to support on-filesystem resources (e.g., extension
20 # modules) in addition to PYZ-embedded ones.
21 #
22 # Therefore, we instead opt for overriding pkgutil.iter_modules with custom implementation that augments the output of
23 # original implementation with contents of PYZ archive from FrozenImporter's TOC.
24 
25 import os
26 import pkgutil
27 import sys
28 
29 from pyimod03_importers import FrozenImporter
30 
31 _orig_pkgutil_iter_modules = pkgutil.iter_modules
32 
33 
34 def _pyi_pkgutil_iter_modules(path=None, prefix=''):
35     # Use original implementation to discover on-filesystem modules (binary extensions in regular builds, or both binary
36     # extensions and compiled pyc modules in noarchive debug builds).
37     yield from _orig_pkgutil_iter_modules(path, prefix)
38 
39     # Find the instance of PyInstaller's FrozenImporter.
40     for importer in pkgutil.iter_importers():
41         if isinstance(importer, FrozenImporter):
42             break
43     else:
44         return
45 
46     if path is None:
47         # Search for all top-level packages/modules. These will have no dots in their entry names.
48         for entry in importer.toc:
49             if entry.count('.') != 0:
50                 continue
51             is_pkg = importer.is_package(entry)
52             yield pkgutil.ModuleInfo(importer, prefix + entry, is_pkg)
53     else:
54         # Declare SYS_PREFIX locally, to avoid clash with eponymous global symbol from pyi_rth_pkgutil hook.
55         SYS_PREFIX = sys._MEIPASS + os.path.sep
56         SYS_PREFIXLEN = len(SYS_PREFIX)
57 
58         for pkg_path in path:
59             pkg_path = os.path.normpath(pkg_path)
60             if not pkg_path.startswith(SYS_PREFIX):
61                 # if the path does not start with sys._MEIPASS then it cannot be a bundled package.
62                 continue
63             # Construct package prefix from path...
64             pkg_prefix = pkg_path[SYS_PREFIXLEN:]
65             pkg_prefix = pkg_prefix.replace(os.path.sep, '.')
66             # ... and ensure it ends with a dot (so we can directly filter out the package itself).
67             if not pkg_prefix.endswith('.'):
68                 pkg_prefix += '.'
69             pkg_prefix_len = len(pkg_prefix)
70 
71             for entry in importer.toc:
72                 if not entry.startswith(pkg_prefix):
73                     continue
74                 name = entry[pkg_prefix_len:]
75                 if name.count('.') != 0:
76                     continue
77                 is_pkg = importer.is_package(entry)
78                 yield pkgutil.ModuleInfo(importer, prefix + name, is_pkg)
79 
80 
81 pkgutil.iter_modules = _pyi_pkgutil_iter_modules
82
```
--- 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/PyInstaller/hooks/rthooks/pyi_rth_pkgutil.py b/PyInstaller/hooks/rthooks/pyi_rth_pkgutil.py
--- a/PyInstaller/hooks/rthooks/pyi_rth_pkgutil.py
+++ b/PyInstaller/hooks/rthooks/pyi_rth_pkgutil.py
@@ -52,11 +52,16 @@
             yield pkgutil.ModuleInfo(importer, prefix + entry, is_pkg)
     else:
         # Declare SYS_PREFIX locally, to avoid clash with eponymous global symbol from pyi_rth_pkgutil hook.
-        SYS_PREFIX = sys._MEIPASS + os.path.sep
+        #
+        # Use os.path.realpath() to fully resolve any symbolic links in sys._MEIPASS, in order to avoid path mis-matches
+        # when the given search paths also contain symbolic links and are already fully resolved. See #6537 for an
+        # example of such a problem with onefile build on macOS, where the temporary directory is placed under /var,
+        # which is actually a symbolic link to /private/var.
+        SYS_PREFIX = os.path.realpath(sys._MEIPASS) + os.path.sep
         SYS_PREFIXLEN = len(SYS_PREFIX)
 
         for pkg_path in path:
-            pkg_path = os.path.normpath(pkg_path)
+            pkg_path = os.path.realpath(pkg_path)  # Fully resolve the given path, in case it contains symbolic links.
             if not pkg_path.startswith(SYS_PREFIX):
                 # if the path does not start with sys._MEIPASS then it cannot be a bundled package.
                 continue

{"golden_diff": "diff --git a/PyInstaller/hooks/rthooks/pyi_rth_pkgutil.py b/PyInstaller/hooks/rthooks/pyi_rth_pkgutil.py\n--- a/PyInstaller/hooks/rthooks/pyi_rth_pkgutil.py\n+++ b/PyInstaller/hooks/rthooks/pyi_rth_pkgutil.py\n@@ -52,11 +52,16 @@\n             yield pkgutil.ModuleInfo(importer, prefix + entry, is_pkg)\n     else:\n         # Declare SYS_PREFIX locally, to avoid clash with eponymous global symbol from pyi_rth_pkgutil hook.\n-        SYS_PREFIX = sys._MEIPASS + os.path.sep\n+        #\n+        # Use os.path.realpath() to fully resolve any symbolic links in sys._MEIPASS, in order to avoid path mis-matches\n+        # when the given search paths also contain symbolic links and are already fully resolved. See #6537 for an\n+        # example of such a problem with onefile build on macOS, where the temporary directory is placed under /var,\n+        # which is actually a symbolic link to /private/var.\n+        SYS_PREFIX = os.path.realpath(sys._MEIPASS) + os.path.sep\n         SYS_PREFIXLEN = len(SYS_PREFIX)\n \n         for pkg_path in path:\n-            pkg_path = os.path.normpath(pkg_path)\n+            pkg_path = os.path.realpath(pkg_path)  # Fully resolve the given path, in case it contains symbolic links.\n             if not pkg_path.startswith(SYS_PREFIX):\n                 # if the path does not start with sys._MEIPASS then it cannot be a bundled package.\n                 continue\n", "issue": "pyi_rth_pkgutil.py hook might not work under MacOS in onefile mode\n## Description of the issue\r\nI'm using `iter_modules` in our cross-platform OpenSource Project [Specter-Desktop](https://github.com/cryptoadvance/specter-desktop) ([spec-file](https://github.com/cryptoadvance/specter-desktop/blob/master/pyinstaller/specterd.spec)).\r\n\r\nFor that, the [pyi_rth_pkgutil.py-hook](https://github.com/pyinstaller/pyinstaller/blob/v4.8/PyInstaller/hooks/rthooks/pyi_rth_pkgutil.py) is quite useful and solved my issue on the linux-platform. However, i have an issue with the MacOS-build at runtime:\r\n```\r\n$  ./dist/specterd server --config=DevelopmentConfig\r\nInitializing HWI...\r\n[2022-01-24 11:49:07,827] INFO in server: Configuration: cryptoadvance.specter.config.DevelopmentConfig\r\n[2022-01-24 11:49:07,828] INFO in specter_migrator: Initiated MigDataManager(/Users/thomasmuller/.specter_dev/migration_data.json events:3 execs:2 )\r\nTraceback (most recent call last):\r\n  File \"specterd.py\", line 4, in <module>\r\n    entry_point()\r\n  File \"click/core.py\", line 829, in __call__\r\n  File \"click/core.py\", line 782, in main\r\n  File \"click/core.py\", line 1259, in invoke\r\n  File \"click/core.py\", line 1066, in invoke\r\n  File \"click/core.py\", line 610, in invoke\r\n  File \"cryptoadvance/specter/cli/cli_server.py\", line 114, in server\r\n  File \"cryptoadvance/specter/server.py\", line 104, in init_app\r\n  File \"cryptoadvance/specter/util/specter_migrator.py\", line 125, in execute_migrations\r\n  File \"cryptoadvance/specter/util/specter_migrator.py\", line 107, in plan_migration\r\n  File \"cryptoadvance/specter/util/specter_migrator.py\", line 161, in get_migration_classes\r\n  File \"PyInstaller/hooks/rthooks/pyi_rth_pkgutil.py\", line 59, in _pyi_pkgutil_iter_modules\r\nAssertionError\r\n[20771] Failed to execute script 'specterd' due to unhandled exception!\r\n(.env) thomasmuller @ Thomass-Air.fritz.box \u279c  pyinstaller git:(service_swan) \u2717\r\n```\r\n\r\nSo the relevant code is this:\r\n```\r\n        SYS_PREFIX = sys._MEIPASS + os.path.sep\r\n        SYS_PREFIXLEN = len(SYS_PREFIX)\r\n        # Only single path is supported, and it must start with sys._MEIPASS.\r\n        pkg_path = os.path.normpath(path[0])\r\n        assert pkg_path.startswith(SYS_PREFIX)\r\n```\r\nSo i inserted some debugging code and figured out that:\r\n\r\n```\r\nSYS_PREFIX: /var/folders/bd/k__jfmz112sb1_dyz4rxwfzh0000gn/T/\r\npkg_path: /private/var/folders/bd/k__jfmz112sb1_dyz4rxwfzh0000gn/T/_MEIBqFxGW/cryptoadvance/specter/util/migrations\r\n```\r\nSo in combination with the comment above, it seems that MacOS is using \"multiple path\" and so MacOS is not supported here?\r\nOn the other hand, this [link](https://difyel.com/apple/macos/macos-directory-structure/#Other_directories) is claiming that `private/var` is only a symlink to `/var`. So i added this and this seem to have solved it?\r\n```\r\n        if pkg_path.startswith(\"/private\"):\r\n                pkg_path = pkg_path[8:]\r\n        assert pkg_path.startswith(SYS_PREFIX)\r\n```\r\nIs this a valid fix? I might  make a PR if someone can give me some guidance on this.\r\n\r\n### Context information (for bug reports)\r\n\r\n* Output of `pyinstaller --version`: ```4.8```\r\n* Version of Python: <!-- e.g. 3.9.7 -->\r\n* Platform: OS X\r\n* How you installed Python: brew\r\n* Did you also try this on another platform? Does it work there? --> Yes, works on Linux\r\n\r\n\n", "before_files": [{"content": "#-----------------------------------------------------------------------------\n# Copyright (c) 2021, PyInstaller Development Team.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n#\n# The full license is in the file COPYING.txt, distributed with this software.\n#\n# SPDX-License-Identifier: Apache-2.0\n#-----------------------------------------------------------------------------\n#\n# This rthook overrides pkgutil.iter_modules with custom implementation that uses PyInstaller's FrozenImporter to list\n# sub-modules embedded in the PYZ archive. The non-embedded modules (binary extensions, or .pyc modules in noarchive\n# build) are handled by original pkgutil iter_modules implementation (and consequently, python's FileFinder).\n#\n# The preferred way of adding support for iter_modules would be adding non-standard iter_modules() method to\n# FrozenImporter itself. However, that seems to work only for path entry finders (for use with sys.path_hooks), while\n# PyInstaller's FrozenImporter is registered as meta path finders (for use with sys.meta_path). Turning FrozenImporter\n# into path entry finder, would seemingly require the latter to support on-filesystem resources (e.g., extension\n# modules) in addition to PYZ-embedded ones.\n#\n# Therefore, we instead opt for overriding pkgutil.iter_modules with custom implementation that augments the output of\n# original implementation with contents of PYZ archive from FrozenImporter's TOC.\n\nimport os\nimport pkgutil\nimport sys\n\nfrom pyimod03_importers import FrozenImporter\n\n_orig_pkgutil_iter_modules = pkgutil.iter_modules\n\n\ndef _pyi_pkgutil_iter_modules(path=None, prefix=''):\n    # Use original implementation to discover on-filesystem modules (binary extensions in regular builds, or both binary\n    # extensions and compiled pyc modules in noarchive debug builds).\n    yield from _orig_pkgutil_iter_modules(path, prefix)\n\n    # Find the instance of PyInstaller's FrozenImporter.\n    for importer in pkgutil.iter_importers():\n        if isinstance(importer, FrozenImporter):\n            break\n    else:\n        return\n\n    if path is None:\n        # Search for all top-level packages/modules. These will have no dots in their entry names.\n        for entry in importer.toc:\n            if entry.count('.') != 0:\n                continue\n            is_pkg = importer.is_package(entry)\n            yield pkgutil.ModuleInfo(importer, prefix + entry, is_pkg)\n    else:\n        # Declare SYS_PREFIX locally, to avoid clash with eponymous global symbol from pyi_rth_pkgutil hook.\n        SYS_PREFIX = sys._MEIPASS + os.path.sep\n        SYS_PREFIXLEN = len(SYS_PREFIX)\n\n        for pkg_path in path:\n            pkg_path = os.path.normpath(pkg_path)\n            if not pkg_path.startswith(SYS_PREFIX):\n                # if the path does not start with sys._MEIPASS then it cannot be a bundled package.\n                continue\n            # Construct package prefix from path...\n            pkg_prefix = pkg_path[SYS_PREFIXLEN:]\n            pkg_prefix = pkg_prefix.replace(os.path.sep, '.')\n            # ... and ensure it ends with a dot (so we can directly filter out the package itself).\n            if not pkg_prefix.endswith('.'):\n                pkg_prefix += '.'\n            pkg_prefix_len = len(pkg_prefix)\n\n            for entry in importer.toc:\n                if not entry.startswith(pkg_prefix):\n                    continue\n                name = entry[pkg_prefix_len:]\n                if name.count('.') != 0:\n                    continue\n                is_pkg = importer.is_package(entry)\n                yield pkgutil.ModuleInfo(importer, prefix + name, is_pkg)\n\n\npkgutil.iter_modules = _pyi_pkgutil_iter_modules\n", "path": "PyInstaller/hooks/rthooks/pyi_rth_pkgutil.py"}], "after_files": [{"content": "#-----------------------------------------------------------------------------\n# Copyright (c) 2021, PyInstaller Development Team.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n#\n# The full license is in the file COPYING.txt, distributed with this software.\n#\n# SPDX-License-Identifier: Apache-2.0\n#-----------------------------------------------------------------------------\n#\n# This rthook overrides pkgutil.iter_modules with custom implementation that uses PyInstaller's FrozenImporter to list\n# sub-modules embedded in the PYZ archive. The non-embedded modules (binary extensions, or .pyc modules in noarchive\n# build) are handled by original pkgutil iter_modules implementation (and consequently, python's FileFinder).\n#\n# The preferred way of adding support for iter_modules would be adding non-standard iter_modules() method to\n# FrozenImporter itself. However, that seems to work only for path entry finders (for use with sys.path_hooks), while\n# PyInstaller's FrozenImporter is registered as meta path finders (for use with sys.meta_path). Turning FrozenImporter\n# into path entry finder, would seemingly require the latter to support on-filesystem resources (e.g., extension\n# modules) in addition to PYZ-embedded ones.\n#\n# Therefore, we instead opt for overriding pkgutil.iter_modules with custom implementation that augments the output of\n# original implementation with contents of PYZ archive from FrozenImporter's TOC.\n\nimport os\nimport pkgutil\nimport sys\n\nfrom pyimod03_importers import FrozenImporter\n\n_orig_pkgutil_iter_modules = pkgutil.iter_modules\n\n\ndef _pyi_pkgutil_iter_modules(path=None, prefix=''):\n    # Use original implementation to discover on-filesystem modules (binary extensions in regular builds, or both binary\n    # extensions and compiled pyc modules in noarchive debug builds).\n    yield from _orig_pkgutil_iter_modules(path, prefix)\n\n    # Find the instance of PyInstaller's FrozenImporter.\n    for importer in pkgutil.iter_importers():\n        if isinstance(importer, FrozenImporter):\n            break\n    else:\n        return\n\n    if path is None:\n        # Search for all top-level packages/modules. These will have no dots in their entry names.\n        for entry in importer.toc:\n            if entry.count('.') != 0:\n                continue\n            is_pkg = importer.is_package(entry)\n            yield pkgutil.ModuleInfo(importer, prefix + entry, is_pkg)\n    else:\n        # Declare SYS_PREFIX locally, to avoid clash with eponymous global symbol from pyi_rth_pkgutil hook.\n        #\n        # Use os.path.realpath() to fully resolve any symbolic links in sys._MEIPASS, in order to avoid path mis-matches\n        # when the given search paths also contain symbolic links and are already fully resolved. See #6537 for an\n        # example of such a problem with onefile build on macOS, where the temporary directory is placed under /var,\n        # which is actually a symbolic link to /private/var.\n        SYS_PREFIX = os.path.realpath(sys._MEIPASS) + os.path.sep\n        SYS_PREFIXLEN = len(SYS_PREFIX)\n\n        for pkg_path in path:\n            pkg_path = os.path.realpath(pkg_path)  # Fully resolve the given path, in case it contains symbolic links.\n            if not pkg_path.startswith(SYS_PREFIX):\n                # if the path does not start with sys._MEIPASS then it cannot be a bundled package.\n                continue\n            # Construct package prefix from path...\n            pkg_prefix = pkg_path[SYS_PREFIXLEN:]\n            pkg_prefix = pkg_prefix.replace(os.path.sep, '.')\n            # ... and ensure it ends with a dot (so we can directly filter out the package itself).\n            if not pkg_prefix.endswith('.'):\n                pkg_prefix += '.'\n            pkg_prefix_len = len(pkg_prefix)\n\n            for entry in importer.toc:\n                if not entry.startswith(pkg_prefix):\n                    continue\n                name = entry[pkg_prefix_len:]\n                if name.count('.') != 0:\n                    continue\n                is_pkg = importer.is_package(entry)\n                yield pkgutil.ModuleInfo(importer, prefix + name, is_pkg)\n\n\npkgutil.iter_modules = _pyi_pkgutil_iter_modules\n", "path": "PyInstaller/hooks/rthooks/pyi_rth_pkgutil.py"}]}