소스 검색

Fix shutdown error in close_httpservers()
"RuntimeError: dictionary changed size during iteration" would sometimes
be thrown. A way to make it happen is to load a page on the web interface.
This was caused by 88dc3edd2d487742def6f3cc3ab63cc85a99e423, before that
change close_httpservers() wasn't called during shutdown.

Mike Naberezny 10 년 전
부모
커밋
ace43df518
1개의 변경된 파일16개의 추가작업 그리고 13개의 파일을 삭제
  1. 16 13
      supervisor/options.py

+ 16 - 13
supervisor/options.py

@@ -1145,24 +1145,27 @@ class ServerOptions(Options):
             pass
 
     def close_httpservers(self):
+        dispatcher_servers = []
         for config, server in self.httpservers:
             server.close()
-            map = self.get_socket_map()
             # server._map is a reference to the asyncore socket_map
-            for dispatcher in map.values():
-                # For unknown reasons, sometimes an http_channel
-                # dispatcher in the socket map related to servers
-                # remains open *during a reload*.  If one of these
-                # exists at this point, we need to close it by hand
-                # (thus removing it from the asyncore.socket_map).  If
-                # we don't do this, 'cleanup_fds' will cause its file
-                # descriptor to be closed, but it will still remain in
-                # the socket_map, and eventually its file descriptor
-                # will be passed to # select(), which will bomb.  See
-                # also http://www.plope.com/software/collector/253
+            for dispatcher in self.get_socket_map().values():
                 dispatcher_server = getattr(dispatcher, 'server', None)
                 if dispatcher_server is server:
-                    dispatcher.close()
+                    dispatcher_servers.append(dispatcher)
+        for server in dispatcher_servers:
+            # TODO: try to remove this entirely.
+            # For unknown reasons, sometimes an http_channel
+            # dispatcher in the socket map related to servers
+            # remains open *during a reload*.  If one of these
+            # exists at this point, we need to close it by hand
+            # (thus removing it from the asyncore.socket_map).  If
+            # we don't do this, 'cleanup_fds' will cause its file
+            # descriptor to be closed, but it will still remain in
+            # the socket_map, and eventually its file descriptor
+            # will be passed to # select(), which will bomb.  See
+            # also http://www.plope.com/software/collector/253
+            server.close()
 
     def close_logger(self):
         self.logger.close()