)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"a295b0a2fd8752d7e0192f129ac12b4e78201554","unresolved":false,"context_lines":[{"line_number":8,"context_line":""},{"line_number":9,"context_line":"Host._conn_event_thread() and, in eventlet mode,"},{"line_number":10,"context_line":"_EventletLibvirtEventHandler._dispatch_thread() never return, and since"},{"line_number":11,"context_line":"Ifcb4b4ad they run on the shared thread pool executor. cleanup() does not"},{"line_number":12,"context_line":"stop them -- its TODO asks for exactly this -- so the executor never"},{"line_number":13,"context_line":"drains and the wait\u003dTrue shutdowns added by I59a3091d block. The service"},{"line_number":14,"context_line":"graceful shutdown then always runs to manager_shutdown_timeout, even when"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":2,"id":"e5ee49a4_23d0ee58","line":11,"updated":"2026-10-12 11:56:42.000000000","message":"the were running in shared executor even before: https://github.com/openstack/nova/commit/a89c1b44c56e04223f61925305b0f48f3791c7d8#diff-67d0163175a798156def4ec53c18fa2ce6eba79b6400fa833a9219d3669e9a11R180","commit_id":"c84d60166dc0a3d1beafcbb6b90ab5705bd97416"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"a295b0a2fd8752d7e0192f129ac12b4e78201554","unresolved":true,"context_lines":[{"line_number":19,"context_line":"what it blocks on: a None sentinel on the connection event queue, and the"},{"line_number":20,"context_line":"wake-up byte _queue_event() already writes to the self-pipe. The pipe is"},{"line_number":21,"context_line":"left open on purpose, as the native libvirt thread writes to it too."},{"line_number":22,"context_line":""},{"line_number":23,"context_line":"Assisted-by: Claude Opus 5"},{"line_number":24,"context_line":"Change-Id: Ie8ef8a7f26d75024d4854559446f12f03bbcad68"},{"line_number":25,"context_line":"Signed-off-by: Gabin Lanore \u003cgabin.lanore@ovhcloud.com\u003e"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":2,"id":"1e1c9d7f_60140f74","line":22,"updated":"2026-10-12 11:56:42.000000000","message":"could you please file a bug so we can track this? I assume we need to backport this at least from Indri to Hibiscus, but also probably to Gazpacho.","commit_id":"c84d60166dc0a3d1beafcbb6b90ab5705bd97416"},{"author":{"_account_id":37706,"name":"Gabin Lanore","display_name":"Gabin Lanore","email":"gabin.lanore@gmail.com","username":"gabin.lanore"},"change_message_id":"b0c1e6c0221a1fc3551050e96471a58e746e1e4e","unresolved":true,"context_lines":[{"line_number":19,"context_line":"what it blocks on: a None sentinel on the connection event queue, and the"},{"line_number":20,"context_line":"wake-up byte _queue_event() already writes to the self-pipe. The pipe is"},{"line_number":21,"context_line":"left open on purpose, as the native libvirt thread writes to it too."},{"line_number":22,"context_line":""},{"line_number":23,"context_line":"Assisted-by: Claude Opus 5"},{"line_number":24,"context_line":"Change-Id: Ie8ef8a7f26d75024d4854559446f12f03bbcad68"},{"line_number":25,"context_line":"Signed-off-by: Gabin Lanore \u003cgabin.lanore@ovhcloud.com\u003e"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":2,"id":"1f5f53be_6b736e3f","line":22,"in_reply_to":"1e1c9d7f_60140f74","updated":"2026-10-13 15:26:25.000000000","message":"I created the bug on launchpad https://bugs.launchpad.net/nova/+bug/2170719. The executor drain (i59a3091d) is on master and stable/2026.2 but not on stable/2026.1, so the backport is needed down to Hibiscus i think. Gazpacho only needs it if i59a3091d gets backported there.","commit_id":"c84d60166dc0a3d1beafcbb6b90ab5705bd97416"}],"/PATCHSET_LEVEL":[{"author":{"_account_id":37706,"name":"Gabin Lanore","display_name":"Gabin Lanore","email":"gabin.lanore@gmail.com","username":"gabin.lanore"},"change_message_id":"63e195499cf16c76ce095b57c20439bdf42d54ed","unresolved":true,"context_lines":[],"source_content_type":"","patch_set":1,"id":"ff6e70f2_dfe2dc0d","updated":"2026-09-11 09:37:36.000000000","message":"recheck nova-grenade-multinode: test_shelve_unshelve_server timed out waiting for network-vif-plugged, unrelated race in shelve offload (instance.host nulled by the second save in _shelve_offload_instance after the unshelve claim already set it)","commit_id":"c35ececb0cc45f5fe29624d71ceb72ee08e3f9ce"},{"author":{"_account_id":37706,"name":"Gabin Lanore","display_name":"Gabin Lanore","email":"gabin.lanore@gmail.com","username":"gabin.lanore"},"change_message_id":"1c4e89815f21fc222ea97f0a4b060a5434397888","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":1,"id":"391c8231_29b7056a","in_reply_to":"fbe7d58d_02f66d5d","updated":"2026-09-16 07:45:46.000000000","message":"Done","commit_id":"c35ececb0cc45f5fe29624d71ceb72ee08e3f9ce"},{"author":{"_account_id":37706,"name":"Gabin Lanore","display_name":"Gabin Lanore","email":"gabin.lanore@gmail.com","username":"gabin.lanore"},"change_message_id":"1d2c45d55688c2b4d62f72323d089ab8d31703ea","unresolved":true,"context_lines":[],"source_content_type":"","patch_set":1,"id":"fbe7d58d_02f66d5d","in_reply_to":"ff6e70f2_dfe2dc0d","updated":"2026-09-14 09:13:17.000000000","message":"recheck nova-grenade-multinode: test_shelve_unshelve_server timed out waiting for network-vif-plugged, unrelated race in shelve offload (instance.host nulled by the second save in _shelve_offload_instance after the unshelve claim already set it)","commit_id":"c35ececb0cc45f5fe29624d71ceb72ee08e3f9ce"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"a295b0a2fd8752d7e0192f129ac12b4e78201554","unresolved":true,"context_lines":[],"source_content_type":"","patch_set":2,"id":"9d0a95cd_c8f6fc8d","updated":"2026-10-12 11:56:42.000000000","message":"Could you propose commit before this with a reproducer added to the graceful shutdown tests to show that graceful shutdown is delayed until the timeout due to this bug?","commit_id":"c84d60166dc0a3d1beafcbb6b90ab5705bd97416"},{"author":{"_account_id":37706,"name":"Gabin Lanore","display_name":"Gabin Lanore","email":"gabin.lanore@gmail.com","username":"gabin.lanore"},"change_message_id":"b0c1e6c0221a1fc3551050e96471a58e746e1e4e","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":2,"id":"81ca8fa3_8661c2ea","in_reply_to":"9d0a95cd_c8f6fc8d","updated":"2026-10-13 15:26:25.000000000","message":"Yup done on https://review.opendev.org/c/openstack/nova/+/1010210","commit_id":"c84d60166dc0a3d1beafcbb6b90ab5705bd97416"}],"nova/virt/libvirt/host.py":[{"author":{"_account_id":11583,"name":"Arnaud Morin","email":"arnaud.morin@gmail.com","username":"arnaudmorin"},"change_message_id":"2d295ca8883fc628ac7ca3a1a8a2c04958473e07","unresolved":false,"context_lines":[{"line_number":210,"context_line":"        # do not close the pipe, as the native libvirt thread writes to it"},{"line_number":211,"context_line":"        # and would race with us."},{"line_number":212,"context_line":"        try:"},{"line_number":213,"context_line":"            self._event_notify_send.write(\u0027 \u0027.encode())"},{"line_number":214,"context_line":"            self._event_notify_send.flush()"},{"line_number":215,"context_line":"        except Exception:"},{"line_number":216,"context_line":"            LOG.exception(\u0027Failed to wake the libvirt event dispatch thread\u0027)"}],"source_content_type":"text/x-python","patch_set":1,"id":"16b61539_3e09e568","line":213,"updated":"2026-09-28 17:04:56.000000000","message":"that sounds like a trick.\nNot that I am against this, but this need to be approved by nova core team","commit_id":"c35ececb0cc45f5fe29624d71ceb72ee08e3f9ce"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"a295b0a2fd8752d7e0192f129ac12b4e78201554","unresolved":false,"context_lines":[{"line_number":149,"context_line":"        LOG.debug(\"Starting event thread\")"},{"line_number":150,"context_line":"        self._event_thread \u003d self.native_threading.Thread("},{"line_number":151,"context_line":"            target\u003dself._native_thread)"},{"line_number":152,"context_line":"        self._event_thread.daemon \u003d True"},{"line_number":153,"context_line":"        self._event_thread.start()"},{"line_number":154,"context_line":""},{"line_number":155,"context_line":"        LOG.debug(\"Starting event dispatch greenthread\")"}],"source_content_type":"text/x-python","patch_set":2,"id":"c64c601a_fcfdd508","line":152,"updated":"2026-10-12 11:56:42.000000000","message":"this thread is free floating so we are not waiting for it","commit_id":"c84d60166dc0a3d1beafcbb6b90ab5705bd97416"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"a295b0a2fd8752d7e0192f129ac12b4e78201554","unresolved":false,"context_lines":[{"line_number":153,"context_line":"        self._event_thread.start()"},{"line_number":154,"context_line":""},{"line_number":155,"context_line":"        LOG.debug(\"Starting event dispatch greenthread\")"},{"line_number":156,"context_line":"        thread_pool_factory.spawn(self._dispatch_thread)"},{"line_number":157,"context_line":""},{"line_number":158,"context_line":"    def _queue_event(self, event):"},{"line_number":159,"context_line":"        \"\"\"Puts an event on the queue for dispatch."}],"source_content_type":"text/x-python","patch_set":2,"id":"76d9a1b8_bd46d737","line":156,"updated":"2026-10-12 11:56:42.000000000","message":"OK so this is a task the graceful shutdown will wait for","commit_id":"c84d60166dc0a3d1beafcbb6b90ab5705bd97416"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"a295b0a2fd8752d7e0192f129ac12b4e78201554","unresolved":true,"context_lines":[{"line_number":227,"context_line":"            _c \u003d self._event_notify_recv.read(1)"},{"line_number":228,"context_line":"            assert _c"},{"line_number":229,"context_line":"        except ValueError:"},{"line_number":230,"context_line":"            return  # will be raised when pipe is closed"},{"line_number":231,"context_line":""},{"line_number":232,"context_line":"        # Process as many events as possible without"},{"line_number":233,"context_line":"        # blocking"}],"source_content_type":"text/x-python","patch_set":2,"id":"e5f90a76_5e948a91","line":230,"updated":"2026-10-12 11:56:42.000000000","message":"this suggests that closing the pipe would be enough to wake the thread from read(1)","commit_id":"c84d60166dc0a3d1beafcbb6b90ab5705bd97416"},{"author":{"_account_id":37706,"name":"Gabin Lanore","display_name":"Gabin Lanore","email":"gabin.lanore@gmail.com","username":"gabin.lanore"},"change_message_id":"b0c1e6c0221a1fc3551050e96471a58e746e1e4e","unresolved":true,"context_lines":[{"line_number":227,"context_line":"            _c \u003d self._event_notify_recv.read(1)"},{"line_number":228,"context_line":"            assert _c"},{"line_number":229,"context_line":"        except ValueError:"},{"line_number":230,"context_line":"            return  # will be raised when pipe is closed"},{"line_number":231,"context_line":""},{"line_number":232,"context_line":"        # Process as many events as possible without"},{"line_number":233,"context_line":"        # blocking"}],"source_content_type":"text/x-python","patch_set":2,"id":"b120b43b_1ec94cda","line":230,"in_reply_to":"e5f90a76_5e948a91","updated":"2026-10-13 15:26:25.000000000","message":"I tried it. Closing the read end doesn\u0027t wake the blocked read(1), and closing the write end makes it return b\u0027\u0027, so we\u0027d hit the assert rather than the ValueError path. The native thread also still writes to it. Writing the wake-up byte felt like the simplest option, but happy to change it if you see a better way.","commit_id":"c84d60166dc0a3d1beafcbb6b90ab5705bd97416"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"a295b0a2fd8752d7e0192f129ac12b4e78201554","unresolved":false,"context_lines":[{"line_number":255,"context_line":"        self._conn_event_handler(conn, False, msg)"},{"line_number":256,"context_line":""},{"line_number":257,"context_line":""},{"line_number":258,"context_line":"class _ThreadingLibvirtEventHandler(LibvirtEventHandler):"},{"line_number":259,"context_line":"    def __init__(self, conn_event_handler\u003dNone, lifecycle_event_handler\u003dNone):"},{"line_number":260,"context_line":"        super().__init__(conn_event_handler, lifecycle_event_handler)"},{"line_number":261,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"06538c41_46dc7c40","line":258,"updated":"2026-10-12 11:56:42.000000000","message":"there is no executor bound threads in this impl, i.e. no equivalent of `_dispatch_thread` from eventlet","commit_id":"c84d60166dc0a3d1beafcbb6b90ab5705bd97416"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"a295b0a2fd8752d7e0192f129ac12b4e78201554","unresolved":false,"context_lines":[{"line_number":270,"context_line":"        libvirt.virEventRegisterDefaultImpl()"},{"line_number":271,"context_line":""},{"line_number":272,"context_line":"        LOG.debug(\"Starting event thread\")"},{"line_number":273,"context_line":"        self._event_thread \u003d threading.Thread(target\u003dself._native_thread)"},{"line_number":274,"context_line":"        self._event_thread.daemon \u003d True"},{"line_number":275,"context_line":"        self._event_thread.start()"},{"line_number":276,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"c05f3736_9f959a9b","line":273,"updated":"2026-10-12 11:56:42.000000000","message":"OK, so this is not a thread from an executor so the graceful shutdown does not wait for this thread to finish. That is probably OK as this is not something that executes long running tasks, it is just pump events from libvirt. If there is a task that are waiting for such event then we expect the task to be tracked by graceful shutdown already.","commit_id":"c84d60166dc0a3d1beafcbb6b90ab5705bd97416"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"a295b0a2fd8752d7e0192f129ac12b4e78201554","unresolved":false,"context_lines":[{"line_number":271,"context_line":""},{"line_number":272,"context_line":"        LOG.debug(\"Starting event thread\")"},{"line_number":273,"context_line":"        self._event_thread \u003d threading.Thread(target\u003dself._native_thread)"},{"line_number":274,"context_line":"        self._event_thread.daemon \u003d True"},{"line_number":275,"context_line":"        self._event_thread.start()"},{"line_number":276,"context_line":""},{"line_number":277,"context_line":"    def _queue_event(self, event):"}],"source_content_type":"text/x-python","patch_set":2,"id":"657565db_40d89a7b","line":274,"updated":"2026-10-12 11:56:42.000000000","message":"as this is a daemon we allow the process to exit even if the event thread is still running. So in summary, we are not waiting for the thread to stop, but it does not block the exit. This sounds good.","commit_id":"c84d60166dc0a3d1beafcbb6b90ab5705bd97416"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"a295b0a2fd8752d7e0192f129ac12b4e78201554","unresolved":true,"context_lines":[{"line_number":319,"context_line":"        # events. In eventlet mode this only pass events within the main"},{"line_number":320,"context_line":"        # native thread with the eventlet hub, so no proxying is needed."},{"line_number":321,"context_line":"        self._conn_event_handler_queue: queue.Queue["},{"line_number":322,"context_line":"            Callable[[], None] | None"},{"line_number":323,"context_line":"        ] \u003d queue.Queue()"},{"line_number":324,"context_line":"        # Set by cleanup() to make _conn_event_thread() return so that the"},{"line_number":325,"context_line":"        # executor it runs on can be drained."}],"source_content_type":"text/x-python","patch_set":2,"id":"850137db_674a61a4","line":322,"updated":"2026-10-12 11:56:42.000000000","message":"I would note here that None vaule is used as a sentinel to indicate that the queue is closed.","commit_id":"c84d60166dc0a3d1beafcbb6b90ab5705bd97416"},{"author":{"_account_id":37706,"name":"Gabin Lanore","display_name":"Gabin Lanore","email":"gabin.lanore@gmail.com","username":"gabin.lanore"},"change_message_id":"b0c1e6c0221a1fc3551050e96471a58e746e1e4e","unresolved":false,"context_lines":[{"line_number":319,"context_line":"        # events. In eventlet mode this only pass events within the main"},{"line_number":320,"context_line":"        # native thread with the eventlet hub, so no proxying is needed."},{"line_number":321,"context_line":"        self._conn_event_handler_queue: queue.Queue["},{"line_number":322,"context_line":"            Callable[[], None] | None"},{"line_number":323,"context_line":"        ] \u003d queue.Queue()"},{"line_number":324,"context_line":"        # Set by cleanup() to make _conn_event_thread() return so that the"},{"line_number":325,"context_line":"        # executor it runs on can be drained."}],"source_content_type":"text/x-python","patch_set":2,"id":"abbdadaa_7336c7c2","line":322,"in_reply_to":"850137db_674a61a4","updated":"2026-10-13 15:26:25.000000000","message":"Done","commit_id":"c84d60166dc0a3d1beafcbb6b90ab5705bd97416"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"a295b0a2fd8752d7e0192f129ac12b4e78201554","unresolved":false,"context_lines":[{"line_number":581,"context_line":"        # In eventlet mode it only handles tasks within the main thread with"},{"line_number":582,"context_line":"        # the eventlet hub."},{"line_number":583,"context_line":"        LOG.debug(\"Starting connection event dispatch thread\")"},{"line_number":584,"context_line":"        thread_pool_factory.spawn(self._conn_event_thread)"},{"line_number":585,"context_line":""},{"line_number":586,"context_line":"    def _get_new_connection(self):"},{"line_number":587,"context_line":"        # call with _wrapped_conn_lock held"}],"source_content_type":"text/x-python","patch_set":2,"id":"a470755d_f387f29b","line":584,"updated":"2026-10-12 11:56:42.000000000","message":"This is another executor bound thread graceful shutdown will wait for.","commit_id":"c84d60166dc0a3d1beafcbb6b90ab5705bd97416"}]}
