)]}'
{"/PATCHSET_LEVEL":[{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"d59a14183086c085a7b1033a73688a7b9d2010eb","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":1,"id":"6dfc4e44_188a07e7","updated":"2026-01-15 17:56:27.000000000","message":"ill push a new revsiosn in a few moments","commit_id":"d25eb1fa945a922dbdc8996a7463bf619337439a"},{"author":{"_account_id":8556,"name":"Ghanshyam Maan","display_name":"Ghanshyam Maan","email":"gmaan.os14@gmail.com","username":"ghanshyam"},"change_message_id":"c2b419831fb7e3a0c81ad616ad2c79539387f561","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":2,"id":"9b28c805_6826c583","updated":"2026-01-29 22:35:44.000000000","message":"I am good on my initial comments about thread safe things but one comment to look into.","commit_id":"8cd03d58cb186f02afc633565f2dfe1f7f931db4"},{"author":{"_account_id":8556,"name":"Ghanshyam Maan","display_name":"Ghanshyam Maan","email":"gmaan.os14@gmail.com","username":"ghanshyam"},"change_message_id":"1f8d98d1531670d49d839d9c3916b499fbc018ae","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":2,"id":"c6bac09c_4df84117","updated":"2026-01-28 04:30:38.000000000","message":"I do not think the removal of self.locks_lock protection will work for multi threading. Adding the details about my finding inline.","commit_id":"8cd03d58cb186f02afc633565f2dfe1f7f931db4"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"c481436e05f906d1d0526caa4b4f3b700123792d","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":2,"id":"0fc5b733_ec434da8","updated":"2026-01-29 13:48:37.000000000","message":"I\u0027ve nothing to add beyond what gmaan has. Just a nit comment inline","commit_id":"8cd03d58cb186f02afc633565f2dfe1f7f931db4"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"45d63b0fc9f973b746e1b0610829f7f8fb99596d","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":2,"id":"3aa64571_38294d90","updated":"2026-01-19 10:23:31.000000000","message":"Thanks. Looks good to me now.","commit_id":"8cd03d58cb186f02afc633565f2dfe1f7f931db4"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"21f2d9464bb44ce6f8e32868ae56cc4751c9f8ca","unresolved":true,"context_lines":[],"source_content_type":"","patch_set":2,"id":"091f5061_efabfca0","in_reply_to":"c6bac09c_4df84117","updated":"2026-01-28 13:57:31.000000000","message":"i have tired to resond as to why i think the propsoed impletion is correct as is\nbut im happy to talk about this more if you like on irc or meet or we can continue the dicussion here.","commit_id":"8cd03d58cb186f02afc633565f2dfe1f7f931db4"},{"author":{"_account_id":8556,"name":"Ghanshyam Maan","display_name":"Ghanshyam Maan","email":"gmaan.os14@gmail.com","username":"ghanshyam"},"change_message_id":"eb745ad449d85b7f44a8eff59c5d68aa2f596ae9","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":3,"id":"591075a0_7b12f883","updated":"2026-02-01 02:29:46.000000000","message":"it seems nova-alt-configurations is broken by recent change in tempest. I will fix it.","commit_id":"100d3191567098d15066cbbf315c3e32bd857084"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"2331b7e680503481a6096143b0c91b1fa1da3c79","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":3,"id":"f62f94bd_7ea39ed0","updated":"2026-02-05 00:01:58.000000000","message":"recheck gate fixed","commit_id":"100d3191567098d15066cbbf315c3e32bd857084"},{"author":{"_account_id":8556,"name":"Ghanshyam Maan","display_name":"Ghanshyam Maan","email":"gmaan.os14@gmail.com","username":"ghanshyam"},"change_message_id":"9dd4a99c0bf48a91cf45dfc0024cd1b12e16724a","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":3,"id":"159969dd_2366f974","updated":"2026-02-02 02:46:55.000000000","message":"recheck nova-alt-configurations is fixed","commit_id":"100d3191567098d15066cbbf315c3e32bd857084"},{"author":{"_account_id":8556,"name":"Ghanshyam Maan","display_name":"Ghanshyam Maan","email":"gmaan.os14@gmail.com","username":"ghanshyam"},"change_message_id":"e8bc880b6ed64910c317aae1e7c75006459b22b5","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":3,"id":"b25a4826_21a79200","updated":"2026-02-01 03:00:02.000000000","message":"thanks for update, lgtm.  nova-alt-configurations is broken, we can re run the tests once fix is merged https://review.opendev.org/c/openstack/tempest/+/975356","commit_id":"100d3191567098d15066cbbf315c3e32bd857084"},{"author":{"_account_id":8556,"name":"Ghanshyam Maan","display_name":"Ghanshyam Maan","email":"gmaan.os14@gmail.com","username":"ghanshyam"},"change_message_id":"e8bc880b6ed64910c317aae1e7c75006459b22b5","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":3,"id":"5fbe9f54_968f1254","in_reply_to":"591075a0_7b12f883","updated":"2026-02-01 03:00:02.000000000","message":"https://review.opendev.org/c/openstack/tempest/+/975356","commit_id":"100d3191567098d15066cbbf315c3e32bd857084"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"5e95a9ef526296c6db3c87e7d5d580d338e89661","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":4,"id":"d0e7bed8_b470e228","updated":"2026-02-18 00:22:19.000000000","message":"recheck ceph job is now fixed","commit_id":"38c8a02e7d68ab36b39934d67752d795340dd3b8"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"4faa030420fef08aa8776a9666058c41d43c7b94","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":4,"id":"259cabe4_1110b17b","updated":"2026-02-12 18:32:42.000000000","message":"recheck openstack.exceptions.DuplicateResource: More than one Service exists with the name \u0027nova-conductor\u0027.\n\ni think there is another flaky test in the devstack functional job","commit_id":"38c8a02e7d68ab36b39934d67752d795340dd3b8"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"f9a73742a6c2986fa93b4dfd0532fc1e08d3b069","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":4,"id":"18073059_a9f68d26","updated":"2026-02-16 12:04:33.000000000","message":"recheck unrelated post failure","commit_id":"38c8a02e7d68ab36b39934d67752d795340dd3b8"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"6010e6dd1fa0c4eb0bb0cdcacdcea0fd0bceff29","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":4,"id":"04abeb1f_67a34187","updated":"2026-02-12 16:07:20.000000000","message":"still OK after the rebase","commit_id":"38c8a02e7d68ab36b39934d67752d795340dd3b8"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"d6231e02d5689a9c469f17e982b38589578e058c","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":5,"id":"03f0c1b5_c1a4010a","updated":"2026-02-18 12:52:35.000000000","message":"rebased instead of recheck to see if the ci isue goes away now.\nit was a diffent postfailure but that looks interminet","commit_id":"72132f89ee4ca7367a6a5639f763f9b20d2c441a"}],"nova/utils.py":[{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"72efc9850247a51d3fd897b439e8c1163f4a454d","unresolved":true,"context_lines":[{"line_number":1158,"context_line":"    return outer_wrapper"},{"line_number":1159,"context_line":""},{"line_number":1160,"context_line":""},{"line_number":1161,"context_line":"class FairLockGuard:"},{"line_number":1162,"context_line":"    \"\"\"A lock guard context manager"},{"line_number":1163,"context_line":""},{"line_number":1164,"context_line":"    This class supports acquiring multiple locks safely by name"}],"source_content_type":"text/x-python","patch_set":1,"id":"edb1b006_b1262dfd","line":1161,"updated":"2026-01-14 20:56:45.000000000","message":"i decided to take the approach of just making the idiot proof\n\nwhile there may be ways to use it that i dislike it shoudl behave correctly even if you do nest this or share it between threads now so we can just review new uasage and decide if the code is understandable as and when this is used more.","commit_id":"d25eb1fa945a922dbdc8996a7463bf619337439a"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"7367db2cd99eda56c1ad28da37cf3df153e75db0","unresolved":false,"context_lines":[{"line_number":1158,"context_line":"    return outer_wrapper"},{"line_number":1159,"context_line":""},{"line_number":1160,"context_line":""},{"line_number":1161,"context_line":"class FairLockGuard:"},{"line_number":1162,"context_line":"    \"\"\"A lock guard context manager"},{"line_number":1163,"context_line":""},{"line_number":1164,"context_line":"    This class supports acquiring multiple locks safely by name"}],"source_content_type":"text/x-python","patch_set":1,"id":"6d21f063_d0f523ec","line":1161,"in_reply_to":"edb1b006_b1262dfd","updated":"2026-01-30 19:21:02.000000000","message":"Acknowledged","commit_id":"d25eb1fa945a922dbdc8996a7463bf619337439a"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"052373f4ac22078411b12e3b45acc8f0d34578ed","unresolved":true,"context_lines":[{"line_number":1172,"context_line":""},{"line_number":1173,"context_line":"    Thread Safety:"},{"line_number":1174,"context_line":"        While sharing a FairLockGuard instance between threads is"},{"line_number":1175,"context_line":"        supported, it is discouraged. Each thread should create its"},{"line_number":1176,"context_line":"        own context manager instance for clarity and to avoid confusion"},{"line_number":1177,"context_line":"        about lock ownership. If shared, threads will correctly wait"},{"line_number":1178,"context_line":"        for each other due to the underlying fair locks."},{"line_number":1179,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"c4fc703d_19c1e216","line":1176,"range":{"start_line":1175,"start_character":39,"end_line":1176,"end_character":36},"updated":"2026-01-15 11:52:26.000000000","message":"nit: ...with the same set of lock names...","commit_id":"d25eb1fa945a922dbdc8996a7463bf619337439a"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"d59a14183086c085a7b1033a73688a7b9d2010eb","unresolved":false,"context_lines":[{"line_number":1172,"context_line":""},{"line_number":1173,"context_line":"    Thread Safety:"},{"line_number":1174,"context_line":"        While sharing a FairLockGuard instance between threads is"},{"line_number":1175,"context_line":"        supported, it is discouraged. Each thread should create its"},{"line_number":1176,"context_line":"        own context manager instance for clarity and to avoid confusion"},{"line_number":1177,"context_line":"        about lock ownership. If shared, threads will correctly wait"},{"line_number":1178,"context_line":"        for each other due to the underlying fair locks."},{"line_number":1179,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"4d832e27_688c56c3","line":1176,"range":{"start_line":1175,"start_character":39,"end_line":1176,"end_character":36},"in_reply_to":"c4fc703d_19c1e216","updated":"2026-01-15 17:56:27.000000000","message":"Done","commit_id":"d25eb1fa945a922dbdc8996a7463bf619337439a"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"052373f4ac22078411b12e3b45acc8f0d34578ed","unresolved":true,"context_lines":[{"line_number":1246,"context_line":"        try:"},{"line_number":1247,"context_line":"            for name in self.names:"},{"line_number":1248,"context_line":"                named_lock \u003d NOVA_FAIR_LOCKS.get(name)"},{"line_number":1249,"context_line":"                acquired_locks.append(named_lock)"},{"line_number":1250,"context_line":"                named_lock.acquire_write_lock()"},{"line_number":1251,"context_line":"        except Exception:"},{"line_number":1252,"context_line":"            # Release any locks acquired so far on failure"}],"source_content_type":"text/x-python","patch_set":1,"id":"1cafc7f6_d6f99eba","line":1249,"updated":"2026-01-15 11:52:26.000000000","message":"this is names `acquired_locks` but at this point the `named_lock` is not yet acquired, that only happens at the next line. In the other hand I agree with the ordering as it is better to record first and then acquire to avoid the case when exception causes that the lock is acquired but not recorded and therefore not release below. \nSo we should keep the order and I have no better suggestion for naming the variable. So probably it is good as is and just a comment is enough explaining that we want this order of actions","commit_id":"d25eb1fa945a922dbdc8996a7463bf619337439a"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"d59a14183086c085a7b1033a73688a7b9d2010eb","unresolved":false,"context_lines":[{"line_number":1246,"context_line":"        try:"},{"line_number":1247,"context_line":"            for name in self.names:"},{"line_number":1248,"context_line":"                named_lock \u003d NOVA_FAIR_LOCKS.get(name)"},{"line_number":1249,"context_line":"                acquired_locks.append(named_lock)"},{"line_number":1250,"context_line":"                named_lock.acquire_write_lock()"},{"line_number":1251,"context_line":"        except Exception:"},{"line_number":1252,"context_line":"            # Release any locks acquired so far on failure"}],"source_content_type":"text/x-python","patch_set":1,"id":"6891eee0_325d9638","line":1249,"in_reply_to":"1cafc7f6_d6f99eba","updated":"2026-01-15 17:56:27.000000000","message":"Done","commit_id":"d25eb1fa945a922dbdc8996a7463bf619337439a"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"052373f4ac22078411b12e3b45acc8f0d34578ed","unresolved":true,"context_lines":[{"line_number":1266,"context_line":"        with self.locks_lock.write_lock():"},{"line_number":1267,"context_line":"            self._nesting_depth -\u003d 1"},{"line_number":1268,"context_line":"            if self._nesting_depth \u003e 0:"},{"line_number":1269,"context_line":"                # Still nested, don\u0027t release locks yet"},{"line_number":1270,"context_line":"                return"},{"line_number":1271,"context_line":""},{"line_number":1272,"context_line":"            my_locks \u003d self.locks"}],"source_content_type":"text/x-python","patch_set":1,"id":"1fc6ecd7_a5e5366d","line":1269,"updated":"2026-01-15 11:52:26.000000000","message":"How does nesting and sharing interacts? During enter we check the current_thread before we increase the nesting level or do a new acquire for a different thread. However here for a nested + shared lock we don\u0027t check if the current thread is the one that has nesting before we decrease the nesting level.\n\nAlso what if two threads, sharing the same guard, independently nesting access to the guard?","commit_id":"d25eb1fa945a922dbdc8996a7463bf619337439a"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"d59a14183086c085a7b1033a73688a7b9d2010eb","unresolved":true,"context_lines":[{"line_number":1266,"context_line":"        with self.locks_lock.write_lock():"},{"line_number":1267,"context_line":"            self._nesting_depth -\u003d 1"},{"line_number":1268,"context_line":"            if self._nesting_depth \u003e 0:"},{"line_number":1269,"context_line":"                # Still nested, don\u0027t release locks yet"},{"line_number":1270,"context_line":"                return"},{"line_number":1271,"context_line":""},{"line_number":1272,"context_line":"            my_locks \u003d self.locks"}],"source_content_type":"text/x-python","patch_set":1,"id":"8811e120_f949b09a","line":1269,"in_reply_to":"1fc6ecd7_a5e5366d","updated":"2026-01-15 17:56:27.000000000","message":"Added a thread check and comment explaing this interaction at the start of __exit__ that validates the exiting thread is the _active_thread. If a different thread calls __exit__ (which shouldn\u0027t happen in normal context manager usage, but could occur with a shared guard), we return early without modifying state. This prevents Thread-B from incorrectly decrementing Thread-A\u0027s nesting depth.\n\nto be clear you really shoudl not eb sharign the context manager or nesting so you double should not do both at the same time but i belive this i relitivly robust to abuse.","commit_id":"d25eb1fa945a922dbdc8996a7463bf619337439a"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"b0b363eedce079fdeb66683feb55effb76683ac5","unresolved":false,"context_lines":[{"line_number":1266,"context_line":"        with self.locks_lock.write_lock():"},{"line_number":1267,"context_line":"            self._nesting_depth -\u003d 1"},{"line_number":1268,"context_line":"            if self._nesting_depth \u003e 0:"},{"line_number":1269,"context_line":"                # Still nested, don\u0027t release locks yet"},{"line_number":1270,"context_line":"                return"},{"line_number":1271,"context_line":""},{"line_number":1272,"context_line":"            my_locks \u003d self.locks"}],"source_content_type":"text/x-python","patch_set":1,"id":"7ce4bfb4_309619a6","line":1269,"in_reply_to":"8811e120_f949b09a","updated":"2026-02-12 16:05:53.000000000","message":"Acknowledged","commit_id":"d25eb1fa945a922dbdc8996a7463bf619337439a"},{"author":{"_account_id":8556,"name":"Ghanshyam Maan","display_name":"Ghanshyam Maan","email":"gmaan.os14@gmail.com","username":"ghanshyam"},"change_message_id":"1f8d98d1531670d49d839d9c3916b499fbc018ae","unresolved":true,"context_lines":[{"line_number":1217,"context_line":"        self._active \u003d False"},{"line_number":1218,"context_line":""},{"line_number":1219,"context_line":"    def __enter__(self):"},{"line_number":1220,"context_line":"        with self.locks_lock.write_lock():"},{"line_number":1221,"context_line":"            if self._active:"},{"line_number":1222,"context_line":"                raise TypeError("},{"line_number":1223,"context_line":"                    \"Cannot enter FairLockGuard while it is already active. \""}],"source_content_type":"text/x-python","patch_set":2,"id":"a1f7409c_111e7f87","side":"PARENT","line":1220,"range":{"start_line":1220,"start_character":7,"end_line":1220,"end_character":42},"updated":"2026-01-28 04:30:38.000000000","message":"though I agree with the deadlock problem you described above (L1242) but removing self.locks_lock undo the FairLocks main concept: \"fair order (FIFO)\"\n\nCase:\nT1 (L1, L2)\nT2 (L1)\nT3 (L2)\n\n- T1 call enter and aquired L1 but before T1 aquires the L2, T2 enter and wait for L1 lock\n- T3 enter and acquires the L2.\n- T1 waiting for T3 which has L2\n- T2 wait for L1 which is held by T1\n- T3 get finish first\n- T1 take L2 and finish\n- T2 take L1 and finish\n\nissue1: This is breaking the logic of \u0027fair\u0027 lock where T3 came after T1 and T2 but got lock and chance to execute the things before them.","commit_id":"d16689b7753e4329af6fa272ed02e8560c010446"},{"author":{"_account_id":8556,"name":"Ghanshyam Maan","display_name":"Ghanshyam Maan","email":"gmaan.os14@gmail.com","username":"ghanshyam"},"change_message_id":"c2b419831fb7e3a0c81ad616ad2c79539387f561","unresolved":false,"context_lines":[{"line_number":1217,"context_line":"        self._active \u003d False"},{"line_number":1218,"context_line":""},{"line_number":1219,"context_line":"    def __enter__(self):"},{"line_number":1220,"context_line":"        with self.locks_lock.write_lock():"},{"line_number":1221,"context_line":"            if self._active:"},{"line_number":1222,"context_line":"                raise TypeError("},{"line_number":1223,"context_line":"                    \"Cannot enter FairLockGuard while it is already active. \""}],"source_content_type":"text/x-python","patch_set":2,"id":"71153a28_4c43c1b7","side":"PARENT","line":1220,"range":{"start_line":1220,"start_character":7,"end_line":1220,"end_character":42},"in_reply_to":"50074d87_0fbcbee1","updated":"2026-01-29 22:35:44.000000000","message":"yeah, if we consider the per lock case it still give the FIFO behaviour and i agree that make sense. considering all set of required lock as single ask is not required. Especially considering the original use case of cleanup of multi-attach volumes.","commit_id":"d16689b7753e4329af6fa272ed02e8560c010446"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"21f2d9464bb44ce6f8e32868ae56cc4751c9f8ca","unresolved":true,"context_lines":[{"line_number":1217,"context_line":"        self._active \u003d False"},{"line_number":1218,"context_line":""},{"line_number":1219,"context_line":"    def __enter__(self):"},{"line_number":1220,"context_line":"        with self.locks_lock.write_lock():"},{"line_number":1221,"context_line":"            if self._active:"},{"line_number":1222,"context_line":"                raise TypeError("},{"line_number":1223,"context_line":"                    \"Cannot enter FairLockGuard while it is already active. \""}],"source_content_type":"text/x-python","patch_set":2,"id":"50074d87_0fbcbee1","side":"PARENT","line":1220,"range":{"start_line":1220,"start_character":7,"end_line":1220,"end_character":42},"in_reply_to":"a1f7409c_111e7f87","updated":"2026-01-28 13:57:31.000000000","message":"it does not break the concept of fairness in my view\n\nLock fairness is defined on a per-lock basis, not as a global ordering of transactions. In your scenario, T1 has not yet requested L2 when T3 arrives. Therefore, the queue for\nL2 is empty, and T3 is legitimately the first thread in line for that specific\nresource.\n\nthe fairness operates on a per lock basis not on all locks.\nwhen T3 entered and aquired l2 it was not \"reserved\" for T1 because it hand not tried to aquire it yet so to mean T3 running before t1 is a prefectly accpetable ordering and is still fiar.\n\nit woudl have also been fair for T2 and T3 to run in parallel and then T1 last or T1 to run and then T2 and T3\n\n\nThere is no \"reservation\" system where acquiring L1 implicitly holds a spot in \nline for L2. For T1 to have priority over L2, it must have already entered the \nL2 wait queue before T3. Since it hadn\u0027t, T3 acquiring the lock and finishing \nfirst is the expected and fair behavior of independent synchronization \nprimitives.\n\nThe expectation that T1 should finish before T3 simply because it started its \nfirst lock acquisition earlier is a requirement for Serializability, not \nFairness. Removing self.locks_lock allows for necessary parallelism where \nthreads use different resources. This change prevents the deadlock\nwhile maintaining the FIFO integrity of each individual lock.\n\nFairness ensures that for a single resource, requests are handled in the order they arrive (FIFO), preventing any one thread from being skipped. In contrast, Serializability is a higher-level guarantee that an entire sequence of operations (like acquiring multiple locks) appears to happen in a specific, total order.\nSerializability is a much higher concurrency constatint that is not required for fairness and not inteded to be provided by this fairlockgurard.\n\n\nthe pirmay usecase for this code is to allow concurrent delete of vms that share at least one mutli attach volume \n\nthis is a very very rare event and ultimalty this is ensureing that one and only one of the two vms we are deleting will actully clean up the volume on the host.\nwe do not actuly care which one that is beyond it being the last one to be deleted.\n\nthe order of which becomes the last to be deleted does not mantter.","commit_id":"d16689b7753e4329af6fa272ed02e8560c010446"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"c481436e05f906d1d0526caa4b4f3b700123792d","unresolved":true,"context_lines":[{"line_number":1186,"context_line":"        instances for nested contexts."},{"line_number":1187,"context_line":""},{"line_number":1188,"context_line":"    Example Recommended Usage:"},{"line_number":1189,"context_line":"    ```"},{"line_number":1190,"context_line":"    # Each context creates its own guard - clear ownership"},{"line_number":1191,"context_line":"    with FairLockGuard([\u0027lock1\u0027, \u0027lock2\u0027]):"},{"line_number":1192,"context_line":"        with FairLockGuard([\u0027lock1\u0027, \u0027lock2\u0027]):"}],"source_content_type":"text/x-python","patch_set":2,"id":"bdfa8efd_d4a84bc7","line":1189,"updated":"2026-01-29 13:48:37.000000000","message":"nit: This is markdown, not rST. You want to use:\n\n```\n::\n\n    # Each context creates its own guard - clear ownership\n    ...\n```\n\nor\n\n```\n\u003e\u003e\u003e # Each context creates its own guard - clear ownership\n\u003e\u003e\u003e with FairLockGuard([\u0027lock1\u0027, \u0027lock2\u0027]):\n...\n```","commit_id":"8cd03d58cb186f02afc633565f2dfe1f7f931db4"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"7367db2cd99eda56c1ad28da37cf3df153e75db0","unresolved":false,"context_lines":[{"line_number":1186,"context_line":"        instances for nested contexts."},{"line_number":1187,"context_line":""},{"line_number":1188,"context_line":"    Example Recommended Usage:"},{"line_number":1189,"context_line":"    ```"},{"line_number":1190,"context_line":"    # Each context creates its own guard - clear ownership"},{"line_number":1191,"context_line":"    with FairLockGuard([\u0027lock1\u0027, \u0027lock2\u0027]):"},{"line_number":1192,"context_line":"        with FairLockGuard([\u0027lock1\u0027, \u0027lock2\u0027]):"}],"source_content_type":"text/x-python","patch_set":2,"id":"d3a7d3ca_9260ceb6","line":1189,"in_reply_to":"0dc5b71f_1c40d16e","updated":"2026-01-30 19:21:02.000000000","message":"Acknowledged","commit_id":"8cd03d58cb186f02afc633565f2dfe1f7f931db4"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"c3325c298c015392a91b755c52d3bbe8a03a2078","unresolved":true,"context_lines":[{"line_number":1186,"context_line":"        instances for nested contexts."},{"line_number":1187,"context_line":""},{"line_number":1188,"context_line":"    Example Recommended Usage:"},{"line_number":1189,"context_line":"    ```"},{"line_number":1190,"context_line":"    # Each context creates its own guard - clear ownership"},{"line_number":1191,"context_line":"    with FairLockGuard([\u0027lock1\u0027, \u0027lock2\u0027]):"},{"line_number":1192,"context_line":"        with FairLockGuard([\u0027lock1\u0027, \u0027lock2\u0027]):"}],"source_content_type":"text/x-python","patch_set":2,"id":"0dc5b71f_1c40d16e","line":1189,"in_reply_to":"bdfa8efd_d4a84bc7","updated":"2026-01-29 14:00:58.000000000","message":"actully it sa docstring so it neither\n\n\nits plain text\nwe do not generate docs form these and we do not use rst or markdown in our docs string in nova.","commit_id":"8cd03d58cb186f02afc633565f2dfe1f7f931db4"},{"author":{"_account_id":8556,"name":"Ghanshyam Maan","display_name":"Ghanshyam Maan","email":"gmaan.os14@gmail.com","username":"ghanshyam"},"change_message_id":"1f8d98d1531670d49d839d9c3916b499fbc018ae","unresolved":true,"context_lines":[{"line_number":1187,"context_line":""},{"line_number":1188,"context_line":"    Example Recommended Usage:"},{"line_number":1189,"context_line":"    ```"},{"line_number":1190,"context_line":"    # Each context creates its own guard - clear ownership"},{"line_number":1191,"context_line":"    with FairLockGuard([\u0027lock1\u0027, \u0027lock2\u0027]):"},{"line_number":1192,"context_line":"        with FairLockGuard([\u0027lock1\u0027, \u0027lock2\u0027]):"},{"line_number":1193,"context_line":"            pass"},{"line_number":1194,"context_line":"    ```"},{"line_number":1195,"context_line":""},{"line_number":1196,"context_line":"    Example Discouraged (but supported) Usage:"}],"source_content_type":"text/x-python","patch_set":2,"id":"be1884af_276fb7ac","line":1193,"range":{"start_line":1190,"start_character":0,"end_line":1193,"end_character":16},"updated":"2026-01-28 04:30:38.000000000","message":"can you please remind me the real use case of this in Nova? where a single thread need a nested lock?","commit_id":"8cd03d58cb186f02afc633565f2dfe1f7f931db4"},{"author":{"_account_id":8556,"name":"Ghanshyam Maan","display_name":"Ghanshyam Maan","email":"gmaan.os14@gmail.com","username":"ghanshyam"},"change_message_id":"c2b419831fb7e3a0c81ad616ad2c79539387f561","unresolved":false,"context_lines":[{"line_number":1187,"context_line":""},{"line_number":1188,"context_line":"    Example Recommended Usage:"},{"line_number":1189,"context_line":"    ```"},{"line_number":1190,"context_line":"    # Each context creates its own guard - clear ownership"},{"line_number":1191,"context_line":"    with FairLockGuard([\u0027lock1\u0027, \u0027lock2\u0027]):"},{"line_number":1192,"context_line":"        with FairLockGuard([\u0027lock1\u0027, \u0027lock2\u0027]):"},{"line_number":1193,"context_line":"            pass"},{"line_number":1194,"context_line":"    ```"},{"line_number":1195,"context_line":""},{"line_number":1196,"context_line":"    Example Discouraged (but supported) Usage:"}],"source_content_type":"text/x-python","patch_set":2,"id":"4100f5f8_e4b732ec","line":1193,"range":{"start_line":1190,"start_character":0,"end_line":1193,"end_character":16},"in_reply_to":"5d7491b0_060ff1e5","updated":"2026-01-29 22:35:44.000000000","message":"oh was it me? I am not sure if I asked for the nested case but anyways it is enough to have a cleay doc string. ok for me.","commit_id":"8cd03d58cb186f02afc633565f2dfe1f7f931db4"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"21f2d9464bb44ce6f8e32868ae56cc4751c9f8ca","unresolved":true,"context_lines":[{"line_number":1187,"context_line":""},{"line_number":1188,"context_line":"    Example Recommended Usage:"},{"line_number":1189,"context_line":"    ```"},{"line_number":1190,"context_line":"    # Each context creates its own guard - clear ownership"},{"line_number":1191,"context_line":"    with FairLockGuard([\u0027lock1\u0027, \u0027lock2\u0027]):"},{"line_number":1192,"context_line":"        with FairLockGuard([\u0027lock1\u0027, \u0027lock2\u0027]):"},{"line_number":1193,"context_line":"            pass"},{"line_number":1194,"context_line":"    ```"},{"line_number":1195,"context_line":""},{"line_number":1196,"context_line":"    Example Discouraged (but supported) Usage:"}],"source_content_type":"text/x-python","patch_set":2,"id":"5d7491b0_060ff1e5","line":1193,"range":{"start_line":1190,"start_character":0,"end_line":1193,"end_character":16},"in_reply_to":"be1884af_276fb7ac","updated":"2026-01-28 13:57:31.000000000","message":"there is none but you kept asking me to support thing this was never intened to supprot to be clear the only usage patther i orginally intened was creating 2 seperate fair lock gaurd instnes in two diffent thread with possible over lapping names.\n\n\nnesting andor sharign the same lock guard instneace ans all of the code to make that work is not needed for any current usecasue and added based on your and gibi orginal feedback.\n\nthese are edge case i originally said i dint want to suport and wnated to review for.\n\ni belive this is a safe implementation of this such that we can now supprot them but i wanted to keep the usage pattres very similar to the synchronised decorator excpet safe for multiple locks","commit_id":"8cd03d58cb186f02afc633565f2dfe1f7f931db4"},{"author":{"_account_id":8556,"name":"Ghanshyam Maan","display_name":"Ghanshyam Maan","email":"gmaan.os14@gmail.com","username":"ghanshyam"},"change_message_id":"1f8d98d1531670d49d839d9c3916b499fbc018ae","unresolved":true,"context_lines":[{"line_number":1259,"context_line":"        acquired_locks \u003d []"},{"line_number":1260,"context_line":"        try:"},{"line_number":1261,"context_line":"            for name in self.names:"},{"line_number":1262,"context_line":"                named_lock \u003d NOVA_FAIR_LOCKS.get(name)"},{"line_number":1263,"context_line":"                acquired_locks.append(named_lock)"},{"line_number":1264,"context_line":"                named_lock.acquire_write_lock()"},{"line_number":1265,"context_line":"        except Exception:"},{"line_number":1266,"context_line":"            # Release any locks acquired so far on failure"},{"line_number":1267,"context_line":"            for lock in acquired_locks:"}],"source_content_type":"text/x-python","patch_set":2,"id":"22c6c0cb_0569e52a","line":1264,"range":{"start_line":1262,"start_character":0,"end_line":1264,"end_character":47},"updated":"2026-01-28 04:30:38.000000000","message":"By removing the self.locks_lock protection, I do not think that \"Support cross-thread sharing\" is something we can do in FairLockGuard by using the lockutils.FairLocks() which internal use fasteners-\u003eReaderWriterLock. If we want to make is multi thread then we need to protect named_lock.acquire_write_lock() under self.locks_lock.\n\nI mean supporting the multithread in FairLockGuard is good idea but then we need to change the implementation. I have not tested it but from code analysis of fasteners ReaderWriterLock, it looks like this is not thread safe for multi writter only case? I noted the below issues:\n\n- Using fasteners-\u003eReaderWriterLock for *multi thread write lock only (no reader)* is not thread safe. I described the issue in [a]\n\n- If nova case does not have reader and need it only for write lock then using ReaderWriterLock is slow where implementation check reader presence. This can be ignored as permornance might not be that impacted. So i am ok on this issue as we use a good amount of implementation from ReaderWriterLock in our case.\n\n\n\n[a]\nUntil I am missing anything, I think the fasteners-\u003eReaderWriterLock-\u003e acquire_write_lock() is not thread safe.\n\nIn the fasteners ReaderWriterLock implementation[1], the internal state \u0027me\u0027 can be changed by two thread before one thread actually aquire the write lock.\n- T1 enter acquire_write_lock() and modify \u0027me\u0027 with me\u003d\u0027T1\u0027 [1]\n- Before T1 call self._acquire_write_lock(me), T2 enter and modify \u0027me\u0027 with me\u003d\u0027T2\u0027 [1].\n- Now T1 call self._acquire_write_lock(me) with \u0027me\u0027 as \u0027T2\u0027[2].\n- T1 aquired the write lock but with name of \u0027T2\u0027. Also modify self._writer as \u0027T2\u0027[3]\n- \n- T2 continue and satisfy self._writer \u003d\u003d me[4] and increament the _writer_entries and get the lock instead of wait for T1 to release the lock.\n\n\n[1] https://github.com/harlowja/fasteners/blob/ea6fce24e8e396813d53d3599f35a22162fb9280/fasteners/lock.py#L209\n\n[2] https://github.com/harlowja/fasteners/blob/ea6fce24e8e396813d53d3599f35a22162fb9280/fasteners/lock.py#L213\n\n[3] https://github.com/harlowja/fasteners/blob/ea6fce24e8e396813d53d3599f35a22162fb9280/fasteners/lock.py#L188\n\n[4] https://github.com/harlowja/fasteners/blob/ea6fce24e8e396813d53d3599f35a22162fb9280/fasteners/lock.py#L211","commit_id":"8cd03d58cb186f02afc633565f2dfe1f7f931db4"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"21f2d9464bb44ce6f8e32868ae56cc4751c9f8ca","unresolved":true,"context_lines":[{"line_number":1259,"context_line":"        acquired_locks \u003d []"},{"line_number":1260,"context_line":"        try:"},{"line_number":1261,"context_line":"            for name in self.names:"},{"line_number":1262,"context_line":"                named_lock \u003d NOVA_FAIR_LOCKS.get(name)"},{"line_number":1263,"context_line":"                acquired_locks.append(named_lock)"},{"line_number":1264,"context_line":"                named_lock.acquire_write_lock()"},{"line_number":1265,"context_line":"        except Exception:"},{"line_number":1266,"context_line":"            # Release any locks acquired so far on failure"},{"line_number":1267,"context_line":"            for lock in acquired_locks:"}],"source_content_type":"text/x-python","patch_set":2,"id":"ec72401a_ddd3003a","line":1264,"range":{"start_line":1262,"start_character":0,"end_line":1264,"end_character":47},"in_reply_to":"22c6c0cb_0569e52a","updated":"2026-01-28 13:57:31.000000000","message":"me is a local variable, not a shared module or instance level variable, so T1 and T2 both have their own independent copies of me in each of their local stack frames, so T1 and T2 can\u0027t interact with the me variable.\n\nTherefore:\n```\ndef acquire_write_lock(self):\n    me \u003d self._current_thread()  # This is a LOCAL variable\n    if self._writer \u003d\u003d me:\n        self._writer_entries +\u003d 1\n    else:\n        self._acquire_write_lock(me)\n```\nis safe with respect to the usage of me.\n\nModifying _writer_entries without having a lock is also safe because the only way the if can be true is if we are currently in the thread that has the lock, and that thread can\u0027t release the lock while it\u0027s executing this stack frame. If eventlet was being used, this would be operating at the greenthread level, so again a greenthread can\u0027t be executing within itself concurrently at two different points in the call stack.\n\nWith that said, it would be better to have the decrement and increment within a lock to have no state modification outside of the lock but its still rentrent without that if only just.\n\nso the question si is, looking deeper at _acquire_write_lock(me) is that function intnerally thread safe (if its not the fastener readerwiter lock is fundamentally broken and this is not a bug in the lock guard but a bug in lockutils and or fasteners .)\n\nLooking at the fasteners implementation at https://github.com/harlowja/fasteners/blob/ea6fce24e8e396813d53d3599f35a22162fb9280/fasteners/lock.py, the _acquire_write_lock function should be thread-safe because\nAll shared state access is protected by with self._cond\n\nThis acquires the underlying lock of the condition variable, ensuring mutual exclusion for all critical sections and effincly causes the thread to sleep until notified by the release of the conditon by the thread that holds it.\n\nThe _pending_writers queue operations (append, popleft, index access) all occur within the with self._cond: block, so they\u0027re properly synchronized.\n\n\n```\n\n        with self._cond:\n            self._pending_writers.append(me)\n            while True:\n                # No readers, and no active writer, am I next??\n                if len(self._readers) \u003d\u003d 0 and self._writer is None:\n                    if self._pending_writers[0] \u003d\u003d me:\n                        self._writer \u003d self._pending_writers.popleft()\n                        self._writer_entries \u003d 1\n                        break\n                self._cond.wait()\n```\n\nthe intere checks fo are there any reader and is ther a current writhere are protected and the sematics fo wait are it relases the lock as the thread is being put to sleeep and when it wakes for notify it will require the lock ro return to sleeping as only one pending waiter will be able to aquire the condition lock.\n\nim not saying there isn\u0027t a bug in the fastener implementaion but i dont think there is a bug in this current usage or the code in this patch in that regard.","commit_id":"8cd03d58cb186f02afc633565f2dfe1f7f931db4"},{"author":{"_account_id":8556,"name":"Ghanshyam Maan","display_name":"Ghanshyam Maan","email":"gmaan.os14@gmail.com","username":"ghanshyam"},"change_message_id":"c2b419831fb7e3a0c81ad616ad2c79539387f561","unresolved":false,"context_lines":[{"line_number":1259,"context_line":"        acquired_locks \u003d []"},{"line_number":1260,"context_line":"        try:"},{"line_number":1261,"context_line":"            for name in self.names:"},{"line_number":1262,"context_line":"                named_lock \u003d NOVA_FAIR_LOCKS.get(name)"},{"line_number":1263,"context_line":"                acquired_locks.append(named_lock)"},{"line_number":1264,"context_line":"                named_lock.acquire_write_lock()"},{"line_number":1265,"context_line":"        except Exception:"},{"line_number":1266,"context_line":"            # Release any locks acquired so far on failure"},{"line_number":1267,"context_line":"            for lock in acquired_locks:"}],"source_content_type":"text/x-python","patch_set":2,"id":"c512ec13_27276081","line":1264,"range":{"start_line":1262,"start_character":0,"end_line":1264,"end_character":47},"in_reply_to":"ec72401a_ddd3003a","updated":"2026-01-29 22:35:44.000000000","message":"you are right, I think I overlooked the \u0027me\u0027 as instance variable (sorruy for that) . with local variable it is all good.","commit_id":"8cd03d58cb186f02afc633565f2dfe1f7f931db4"},{"author":{"_account_id":8556,"name":"Ghanshyam Maan","display_name":"Ghanshyam Maan","email":"gmaan.os14@gmail.com","username":"ghanshyam"},"change_message_id":"1f8d98d1531670d49d839d9c3916b499fbc018ae","unresolved":true,"context_lines":[{"line_number":1278,"context_line":""},{"line_number":1279,"context_line":"    def __exit__(self, exc_type, exc_value, traceback):"},{"line_number":1280,"context_line":"        current_thread \u003d threading.current_thread()"},{"line_number":1281,"context_line":"        with self.locks_lock.write_lock():"},{"line_number":1282,"context_line":"            # Validate the exiting thread owns the lock. This handles the"},{"line_number":1283,"context_line":"            # edge case where a shared guard\u0027s __exit__ is called from a"},{"line_number":1284,"context_line":"            # thread that didn\u0027t successfully __enter__ (e.g., Thread-B"}],"source_content_type":"text/x-python","patch_set":2,"id":"3f9e186d_4a53bc52","line":1281,"range":{"start_line":1281,"start_character":0,"end_line":1281,"end_character":42},"updated":"2026-01-28 04:30:38.000000000","message":"so the main problem  is this one. what if we use the different locks in  __enter__ and __exit__?\n\nWitrh that we need to update self.locks.append(named_lock) in __enter__  after lock is actually acquired then we will make sure that self.locks is is in good state while any thread releasing the self.locks in  __exit__","commit_id":"8cd03d58cb186f02afc633565f2dfe1f7f931db4"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"21f2d9464bb44ce6f8e32868ae56cc4751c9f8ca","unresolved":true,"context_lines":[{"line_number":1278,"context_line":""},{"line_number":1279,"context_line":"    def __exit__(self, exc_type, exc_value, traceback):"},{"line_number":1280,"context_line":"        current_thread \u003d threading.current_thread()"},{"line_number":1281,"context_line":"        with self.locks_lock.write_lock():"},{"line_number":1282,"context_line":"            # Validate the exiting thread owns the lock. This handles the"},{"line_number":1283,"context_line":"            # edge case where a shared guard\u0027s __exit__ is called from a"},{"line_number":1284,"context_line":"            # thread that didn\u0027t successfully __enter__ (e.g., Thread-B"}],"source_content_type":"text/x-python","patch_set":2,"id":"47a78758_71c89348","line":1281,"range":{"start_line":1281,"start_character":0,"end_line":1281,"end_character":42},"in_reply_to":"3f9e186d_4a53bc52","updated":"2026-01-28 13:57:31.000000000","message":"how would that happen the lock names are fixed when you constuct the context manganger as part of __init__\n\nin enther and exit we are just aquireing and release a fixed set of locks\nand we check if we have the lock before releasing it","commit_id":"8cd03d58cb186f02afc633565f2dfe1f7f931db4"},{"author":{"_account_id":8556,"name":"Ghanshyam Maan","display_name":"Ghanshyam Maan","email":"gmaan.os14@gmail.com","username":"ghanshyam"},"change_message_id":"c2b419831fb7e3a0c81ad616ad2c79539387f561","unresolved":false,"context_lines":[{"line_number":1278,"context_line":""},{"line_number":1279,"context_line":"    def __exit__(self, exc_type, exc_value, traceback):"},{"line_number":1280,"context_line":"        current_thread \u003d threading.current_thread()"},{"line_number":1281,"context_line":"        with self.locks_lock.write_lock():"},{"line_number":1282,"context_line":"            # Validate the exiting thread owns the lock. This handles the"},{"line_number":1283,"context_line":"            # edge case where a shared guard\u0027s __exit__ is called from a"},{"line_number":1284,"context_line":"            # thread that didn\u0027t successfully __enter__ (e.g., Thread-B"}],"source_content_type":"text/x-python","patch_set":2,"id":"4c34c53b_fe9bde21","line":1281,"range":{"start_line":1281,"start_character":0,"end_line":1281,"end_character":42},"in_reply_to":"47a78758_71c89348","updated":"2026-01-29 22:35:44.000000000","message":"all good here as acquire_write_lock is thread safe so no changes needed","commit_id":"8cd03d58cb186f02afc633565f2dfe1f7f931db4"},{"author":{"_account_id":8556,"name":"Ghanshyam Maan","display_name":"Ghanshyam Maan","email":"gmaan.os14@gmail.com","username":"ghanshyam"},"change_message_id":"c2b419831fb7e3a0c81ad616ad2c79539387f561","unresolved":true,"context_lines":[{"line_number":1294,"context_line":"                return"},{"line_number":1295,"context_line":""},{"line_number":1296,"context_line":"            my_locks \u003d self.locks"},{"line_number":1297,"context_line":"            self.locks \u003d []"},{"line_number":1298,"context_line":"            self._active \u003d False"},{"line_number":1299,"context_line":"            self._active_thread \u003d None"},{"line_number":1300,"context_line":""},{"line_number":1301,"context_line":"        # Release locks OUTSIDE of locks_lock to prevent holding it"},{"line_number":1302,"context_line":"        # while other threads may be waiting"}],"source_content_type":"text/x-python","patch_set":2,"id":"ff4bb8ea_53533e58","line":1299,"range":{"start_line":1297,"start_character":0,"end_line":1299,"end_character":38},"updated":"2026-01-29 22:35:44.000000000","message":"I think we should do these after L1305 once locks are actually released. If any issue on releasing locks then we rest these variable and there might be unreleased locks.","commit_id":"8cd03d58cb186f02afc633565f2dfe1f7f931db4"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"7367db2cd99eda56c1ad28da37cf3df153e75db0","unresolved":false,"context_lines":[{"line_number":1294,"context_line":"                return"},{"line_number":1295,"context_line":""},{"line_number":1296,"context_line":"            my_locks \u003d self.locks"},{"line_number":1297,"context_line":"            self.locks \u003d []"},{"line_number":1298,"context_line":"            self._active \u003d False"},{"line_number":1299,"context_line":"            self._active_thread \u003d None"},{"line_number":1300,"context_line":""},{"line_number":1301,"context_line":"        # Release locks OUTSIDE of locks_lock to prevent holding it"},{"line_number":1302,"context_line":"        # while other threads may be waiting"}],"source_content_type":"text/x-python","patch_set":2,"id":"e7fe505a_87968675","line":1299,"range":{"start_line":1297,"start_character":0,"end_line":1299,"end_character":38},"in_reply_to":"34fbdb5c_7e5711af","updated":"2026-01-30 19:21:02.000000000","message":"Done i pulled the loop out into a function and reordered its as discussed","commit_id":"8cd03d58cb186f02afc633565f2dfe1f7f931db4"},{"author":{"_account_id":8556,"name":"Ghanshyam Maan","display_name":"Ghanshyam Maan","email":"gmaan.os14@gmail.com","username":"ghanshyam"},"change_message_id":"1a8eee474d5aa272a3fb4082e96dfc5cf33ff1d2","unresolved":true,"context_lines":[{"line_number":1294,"context_line":"                return"},{"line_number":1295,"context_line":""},{"line_number":1296,"context_line":"            my_locks \u003d self.locks"},{"line_number":1297,"context_line":"            self.locks \u003d []"},{"line_number":1298,"context_line":"            self._active \u003d False"},{"line_number":1299,"context_line":"            self._active_thread \u003d None"},{"line_number":1300,"context_line":""},{"line_number":1301,"context_line":"        # Release locks OUTSIDE of locks_lock to prevent holding it"},{"line_number":1302,"context_line":"        # while other threads may be waiting"}],"source_content_type":"text/x-python","patch_set":2,"id":"34fbdb5c_7e5711af","line":1299,"range":{"start_line":1297,"start_character":0,"end_line":1299,"end_character":38},"in_reply_to":"68d11fdc_196dd2e0","updated":"2026-01-30 18:41:30.000000000","message":"I think passing the exception is safe way and that can also prevent if exception occur during first lock release it will not prevent other locks release. I think this should work fine. I am not sure we need __del__\n\n    # Release locks OUTSIDE of locks_lock to prevent holding it\n    # while other threads may be waiting\n    for lock in self.locks:\n        if lock.is_writer():\n        try:\n            lock.release_write_lock()\n        excpet Excpetion:\n           pass\n\n    with self.locks_lock.write_lock():\n         self.locks \u003d []\n         self._active \u003d False\n         self._active_thread \u003d None","commit_id":"8cd03d58cb186f02afc633565f2dfe1f7f931db4"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"7823595e793e2600e36915854de4986e1e49e44d","unresolved":true,"context_lines":[{"line_number":1294,"context_line":"                return"},{"line_number":1295,"context_line":""},{"line_number":1296,"context_line":"            my_locks \u003d self.locks"},{"line_number":1297,"context_line":"            self.locks \u003d []"},{"line_number":1298,"context_line":"            self._active \u003d False"},{"line_number":1299,"context_line":"            self._active_thread \u003d None"},{"line_number":1300,"context_line":""},{"line_number":1301,"context_line":"        # Release locks OUTSIDE of locks_lock to prevent holding it"},{"line_number":1302,"context_line":"        # while other threads may be waiting"}],"source_content_type":"text/x-python","patch_set":2,"id":"68d11fdc_196dd2e0","line":1299,"range":{"start_line":1297,"start_character":0,"end_line":1299,"end_character":38},"in_reply_to":"ff4bb8ea_53533e58","updated":"2026-01-30 18:18:10.000000000","message":"thinking this through\n\nif i move it after so \n```\n    # Release locks OUTSIDE of locks_lock to prevent holding it\n    # while other threads may be waiting\n    for lock in my_locks:\n        if lock.is_writer():\n            lock.release_write_lock()\n\n    with self.locks_lock.write_lock():\n         self.locks \u003d []\n         self._active \u003d False\n         self._active_thread \u003d None\n\n```\nim still iteratig over the same list as i was nto makging a copy so it can be\n\n```\n    # Release locks OUTSIDE of locks_lock to prevent holding it\n    # while other threads may be waiting\n    for lock in self.locks:\n        if lock.is_writer():\n            lock.release_write_lock()\n\n    with self.locks_lock.write_lock():\n         self.locks \u003d []\n         self._active \u003d False\n         self._active_thread \u003d None\n\n```\nlock.release_write_lock does not invalidate the iterator\nso that is safe regardless.\n\ni think this order is also ok but it does meani have to drop and reaquire the lock_lock when im modifying the instenal state of the \n\n\nthe only way lock.release_write_lock() can rasie is if we are not currently the writer which si why the if is there\n\nhttps://github.com/harlowja/fasteners/blob/06c3f06cab4e135b8d921932019a231c180eb9f4/fasteners/lock.py#L215-L227\n\ngiven we typically wont have a reffence to the context manger object if we were to raise (i dont think we can) then i don tsee how we could ever catch the excption adn call __exit__ agian.\n\n\n\nso to improve the error handelign more i woudl have to do \n\n\n```\n    # Release locks OUTSIDE of locks_lock to prevent holding it\n    # while other threads may be waiting\n    for lock in self.locks:\n        if lock.is_writer():\n        try:\n            lock.release_write_lock()\n        excpet Excpetion:\n           pass\n\n    with self.locks_lock.write_lock():\n         self.locks \u003d []\n         self._active \u003d False\n         self._active_thread \u003d None\n         \n    def __del__(self):\n    if not self.locks:\n      return\n    for lock in self.locks:\n        if lock.is_writer():\n        try:\n            lock.release_write_lock()\n        excpet Excpetion:\n           pass\n```\n\nif we really want that to try and release again on destruction of the context manager after it failed on __exit__\ni can  do this but i would prefer not.\n\nlet me know either way","commit_id":"8cd03d58cb186f02afc633565f2dfe1f7f931db4"}]}
