\ Spawn the dirty arbiter process. The dirty arbiter manages a separate pool of workers for long-running, blocking operations.
(self)
| 836 | pass |
| 837 | |
| 838 | def spawn_dirty_arbiter(self): |
| 839 | """\ |
| 840 | Spawn the dirty arbiter process. |
| 841 | |
| 842 | The dirty arbiter manages a separate pool of workers for |
| 843 | long-running, blocking operations. |
| 844 | """ |
| 845 | # Lazy import for gevent compatibility (see #3482) |
| 846 | from gunicorn.dirty import DirtyArbiter, set_dirty_socket_path |
| 847 | |
| 848 | if self.dirty_arbiter_pid: |
| 849 | return # Already running |
| 850 | |
| 851 | # Cleanup any orphaned dirty arbiter from previous crash |
| 852 | self._cleanup_orphaned_dirty_arbiter() |
| 853 | |
| 854 | # Get well-known PID file path |
| 855 | self.dirty_pidfile = self._get_dirty_pidfile_path() |
| 856 | |
| 857 | self.dirty_arbiter = DirtyArbiter( |
| 858 | self.cfg, self.log, |
| 859 | pidfile=self.dirty_pidfile |
| 860 | ) |
| 861 | socket_path = self.dirty_arbiter.socket_path |
| 862 | |
| 863 | pid = os.fork() |
| 864 | if pid != 0: |
| 865 | # Parent process |
| 866 | self.dirty_arbiter_pid = pid |
| 867 | # Set socket path for HTTP workers to use |
| 868 | set_dirty_socket_path(socket_path) |
| 869 | os.environ['GUNICORN_DIRTY_SOCKET'] = socket_path |
| 870 | self.log.info("Spawned dirty arbiter (pid: %s) at %s", |
| 871 | pid, socket_path) |
| 872 | return pid |
| 873 | |
| 874 | # Child process - run the dirty arbiter |
| 875 | try: |
| 876 | self.dirty_arbiter.run() |
| 877 | sys.exit(0) |
| 878 | except SystemExit: |
| 879 | raise |
| 880 | except Exception: |
| 881 | self.log.exception("Exception in dirty arbiter process") |
| 882 | sys.exit(-1) |
| 883 | |
| 884 | def kill_dirty_arbiter(self, sig): |
| 885 | """\ |