)]}'
{"/PATCHSET_LEVEL":[{"author":{"_account_id":7730,"name":"Sahid Orentino Ferdjaoui","email":"sahid.ferdjaoui@industrialdiscipline.com","username":"sahid"},"change_message_id":"be013b37fe97270a4913873c68cb60b47aac5c4f","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":1,"id":"68bc6822_be8052f6","updated":"2025-01-16 11:04:28.000000000","message":"recheck","commit_id":"3a6c5f19bccea5ca108a892089432de77eb38570"},{"author":{"_account_id":7730,"name":"Sahid Orentino Ferdjaoui","email":"sahid.ferdjaoui@industrialdiscipline.com","username":"sahid"},"change_message_id":"828f84cdde6e6685f2f0fbaa0b04bddae57ff452","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":2,"id":"49bebe04_d4252ab2","updated":"2025-01-16 16:48:01.000000000","message":"recheck unrelated","commit_id":"153f6641e14fb03ebc56a25d03c331f8caca0fb5"},{"author":{"_account_id":1131,"name":"Brian Haley","email":"haleyb.dev@gmail.com","username":"brian-haley"},"change_message_id":"199217a3b61d8769b1d7c3a46b68b3174003203f","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":13,"id":"3e17a8c6_6392adf9","updated":"2025-01-27 20:00:44.000000000","message":"recheck parent change gate failure","commit_id":"af4b1da59a4798ca950ce3be69a8f9b95bb35243"}],"neutron/agent/common/async_process.py":[{"author":{"_account_id":16688,"name":"Rodolfo Alonso","email":"ralonsoh@redhat.com","username":"rodolfo-alonso-hernandez"},"change_message_id":"194e3498b3c0d16d17c38a36fcd8c4a757056a54","unresolved":true,"context_lines":[{"line_number":266,"context_line":"                LOG.exception(\u0027An error occurred while communicating \u0027"},{"line_number":267,"context_line":"                              \u0027with async process [%s].\u0027, self.cmd)"},{"line_number":268,"context_line":"                break"},{"line_number":269,"context_line":"            time.sleep(0.1)"},{"line_number":270,"context_line":""},{"line_number":271,"context_line":"        # self._is_running being True indicates that the loop was"},{"line_number":272,"context_line":"        # broken out of due to an error in the watched process rather"}],"source_content_type":"text/x-python","patch_set":3,"id":"d272208e_7a28cb10","line":269,"range":{"start_line":269,"start_character":23,"end_line":269,"end_character":26},"updated":"2025-01-17 11:15:24.000000000","message":"This could (should) be 0\n\nUPDATE: actually this number must be 0. The FT is failing because of this.\n\nUPDATE2: I\u0027ve been reviewing this whole class. With sleep(0.1) or more, we can check that is racy. For each process, two threads are spawn, one of the stdout and another for the stderr. The problem here is that usually the stderr attends event of the killed process and sets ``self._is_running \u003d False``.\n\nIf time is bigger than 0.1, the stdout thread will be waiting. During this time, the main thread has spawned two new threads for the new process and set ``self._is_running \u003d True``. That mean when the old thread for stdout ends the sleep, it fails (the old pid is no longer running) and executes the ``_handle_process_error``.\n\nThat triggers and endless loop of kill-respawn executions.\n\nWhat should be done here? We need to pass a local \"is_running\" event, only for the two threads that are monitoring a PID. Something like this:\n```\n    def _spawn(self):\n        \"\"\"Spawn a process and its watchers.\"\"\"\n        self._is_running \u003d True\n        self._pid \u003d None\n        self._kill_event \u003d threading.Event()\n        is_running \u003d threading.Event()\n        self._process, cmd \u003d utils.create_process(self._cmd,\n                                                  run_as_root\u003dself.run_as_root)\n        self._watchers \u003d []\n        for reader in (self._read_stdout, self._read_stderr):\n            # Pass the stop event directly to the thread to\n            # ensure that assignment of a new event to the instance\n            # attribute does not prevent the thread from using\n            # the original event.\n            watcher \u003d threading.Thread(\n                target\u003dself._watch_process,\n                args\u003d(reader, self._kill_event, is_running),\n                # Let a chance to terminate properly with event mech\n                daemon\u003dFalse)\n            watcher.start()\n            self._watchers.append(watcher)\n\n    def _watch_process(self, callback, kill_event, is_running):\n    [...]\n        if not is_running.is_set():\n            is_running.set()  # That will prevent the other thread\n                              # to execute ``_handle_process_error``\n            self._is_running \u003d False  # That will define the process\n                                      # as stopped.\n            self._handle_process_error()\n```","commit_id":"1ef56c74c11e7ff201a97015406b643919fe6f0c"},{"author":{"_account_id":7730,"name":"Sahid Orentino Ferdjaoui","email":"sahid.ferdjaoui@industrialdiscipline.com","username":"sahid"},"change_message_id":"bed6d9b43993178dcdc3df8d59eba83443848fce","unresolved":true,"context_lines":[{"line_number":266,"context_line":"                LOG.exception(\u0027An error occurred while communicating \u0027"},{"line_number":267,"context_line":"                              \u0027with async process [%s].\u0027, self.cmd)"},{"line_number":268,"context_line":"                break"},{"line_number":269,"context_line":"            time.sleep(0.1)"},{"line_number":270,"context_line":""},{"line_number":271,"context_line":"        # self._is_running being True indicates that the loop was"},{"line_number":272,"context_line":"        # broken out of due to an error in the watched process rather"}],"source_content_type":"text/x-python","patch_set":3,"id":"fceea8e3_8102033d","line":269,"range":{"start_line":269,"start_character":23,"end_line":269,"end_character":26},"in_reply_to":"d272208e_7a28cb10","updated":"2025-01-20 11:25:38.000000000","message":"Hum not sure why I have put this to 0.1 but actually that highlight an interesting bug :-) Thanks I will provide a fix for that one.","commit_id":"1ef56c74c11e7ff201a97015406b643919fe6f0c"},{"author":{"_account_id":16688,"name":"Rodolfo Alonso","email":"ralonsoh@redhat.com","username":"rodolfo-alonso-hernandez"},"change_message_id":"d892704976af6cd3a50e022ab0dbda4e9c440b9c","unresolved":false,"context_lines":[{"line_number":266,"context_line":"                LOG.exception(\u0027An error occurred while communicating \u0027"},{"line_number":267,"context_line":"                              \u0027with async process [%s].\u0027, self.cmd)"},{"line_number":268,"context_line":"                break"},{"line_number":269,"context_line":"            time.sleep(0.1)"},{"line_number":270,"context_line":""},{"line_number":271,"context_line":"        # self._is_running being True indicates that the loop was"},{"line_number":272,"context_line":"        # broken out of due to an error in the watched process rather"}],"source_content_type":"text/x-python","patch_set":3,"id":"4c89ab72_ee46e75a","line":269,"range":{"start_line":269,"start_character":23,"end_line":269,"end_character":26},"in_reply_to":"fceea8e3_8102033d","updated":"2025-01-23 15:50:14.000000000","message":"Done","commit_id":"1ef56c74c11e7ff201a97015406b643919fe6f0c"}]}
