Title: SymbolicReference.set_reference may not roll back properly on error · Issue #1669 · gitpython-developers/GitPython · GitHub
Open Graph Title: SymbolicReference.set_reference may not roll back properly on error · Issue #1669 · gitpython-developers/GitPython
X Title: SymbolicReference.set_reference may not roll back properly on error · Issue #1669 · gitpython-developers/GitPython
Description: SymbolicReference.set_reference contains this code, which is meant to attempt a transactional write: GitPython/git/refs/symbolic.py Lines 373 to 380 in a5a6464 ok = True try: fd.write(write_value.encode("utf-8") + b"\n") lfd.commit() ok ...
Open Graph Description: SymbolicReference.set_reference contains this code, which is meant to attempt a transactional write: GitPython/git/refs/symbolic.py Lines 373 to 380 in a5a6464 ok = True try: fd.write(write_value.e...
X Description: SymbolicReference.set_reference contains this code, which is meant to attempt a transactional write: GitPython/git/refs/symbolic.py Lines 373 to 380 in a5a6464 ok = True try: fd.write(write_value.e...
Opengraph URL: https://github.com/gitpython-developers/GitPython/issues/1669
X: @github
Domain: github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"SymbolicReference.set_reference may not roll back properly on error","articleBody":"`SymbolicReference.set_reference` contains this code, which is meant to attempt a transactional write:\r\n\r\nhttps://github.com/gitpython-developers/GitPython/blob/a5a646494393478c65f26cd3a921f3505219d3e1/git/refs/symbolic.py#L373-L380\r\n\r\nHowever, because the `ok` flag is *initialized* to `True` instead of `False`--which strongly appears unintentional--it is always `True` even if the `ok = True` statement in the `try` block is not reached. Consequently, `lfd.rollback()` in the `finally` block is never called. This seems on first glance like a serious bug, but as detailed below I believe it might actually be quite minor in the context of what kind of cleanup GitPython generally [does or does not guarantee](https://github.com/gitpython-developers/GitPython?tab=readme-ov-file#leakage-of-system-resources).\r\n\r\nThis can be contrasted to another place where that pattern is used correctly:\r\n\r\nhttps://github.com/gitpython-developers/GitPython/blob/a5a646494393478c65f26cd3a921f3505219d3e1/git/index/base.py#L227-L233\r\n\r\nThis is very simple to fix, since it is sufficient to change `True` to `False` in the initial assignment. So most of the work to fix it would be figuring out where a regression test should go and how it should manage to produce a case where cleanup doesn't happen immediately.\r\n\r\n(Besides that simple fix, other fixes that also reduce the risk of such bugs coming back and allow the code to be simplified are possible. In particular, the `LockedFD` object represents a non-memory resource that always can and should be managed deterministically according to where control flow is, so it ought to implement the context manager protocol.)\r\n\r\nI am unsure if this bug causes any problems in practice. If I understand [`LockedFD`](https://github.com/gitpython-developers/gitdb/blob/master/gitdb/util.py#L269) correctly, the write that is not rolled back is to a temporary file separate from the real target, accessed through a file object specific to that `LockedFD` object. The lock file name is determined from the target file name, so if a separate attempt to write to the target is made, that could cause problems. `LockedFD` has a `__del__` method that should be called eventually and performs the rollback. On CPython, which has reference counting as its primary garbage collection strategy, cleanup would often happen immediately as a result... though not always, even in the absence of reference cycles, because, in exception handling, an exception object holds a reference to a traceback object which holds references to all stack frames in its call stack, through which local variables thus remain accessible until control leaves the handling `except` block.\r\n\r\nStill, it may be that this shall not be considered a bug--or at least not a bug of its own, or at least not a bug that merits a regression test accompanying its bugfix--on the grounds that **it might be considered a special case of the [Leakage of System Resources](https://github.com/gitpython-developers/GitPython?tab=readme-ov-file#leakage-of-system-resources) limitation** documented prominently in the readme. In support of this view, the third place in the code of GitPython where `ldf.rollback` is called uses a different pattern and its comments suggest that cleanup via `LockedFD.__del__` is considered acceptable to rely on:\r\n\r\nhttps://github.com/gitpython-developers/GitPython/blob/a5a646494393478c65f26cd3a921f3505219d3e1/git/refs/log.py#L261-L268\r\n\r\n(Interestingly, that is not exactly equivalent to the behavior of the `try`-`finally` pattern used in `git/index/base.py`. If it is intended to be, then it should catch `BaseException` rather than `Exception`.)","author":{"url":"https://github.com/EliahKagan","@type":"Person","name":"EliahKagan"},"datePublished":"2023-09-21T08:14:24.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":7},"url":"https://github.com/1669/GitPython/issues/1669"}
| route-pattern | /_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format) |
| route-controller | voltron_issues_fragments |
| route-action | issue_layout |
| fetch-nonce | v2:2d05a527-fe10-e0a4-91e5-c6c296b99df5 |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | A4D2:1DF50E:885945:B6FD8D:69683790 |
| html-safe-nonce | 874e36e6c2a192486adbbe58d6bcb54226f670eea5410340ab6a555f6000b26c |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJBNEQyOjFERjUwRTo4ODU5NDU6QjZGRDhEOjY5NjgzNzkwIiwidmlzaXRvcl9pZCI6Ijc3MDk3NDA2MzA1MzQ1MzUwNTYiLCJyZWdpb25fZWRnZSI6ImlhZCIsInJlZ2lvbl9yZW5kZXIiOiJpYWQifQ== |
| visitor-hmac | 9966ce322df4b4d4a8912f191e378129906afd58a4fbdbf98ecd692ab8c8ecb7 |
| hovercard-subject-tag | issue:1906380130 |
| github-keyboard-shortcuts | repository,issues,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/gitpython-developers/GitPython/1669/issue_layout |
| twitter:image | https://opengraph.githubassets.com/5ad75d075c2d000c384182110fc6e769dc1f377961cb62891d007aae0703766f/gitpython-developers/GitPython/issues/1669 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/5ad75d075c2d000c384182110fc6e769dc1f377961cb62891d007aae0703766f/gitpython-developers/GitPython/issues/1669 |
| og:image:alt | SymbolicReference.set_reference contains this code, which is meant to attempt a transactional write: GitPython/git/refs/symbolic.py Lines 373 to 380 in a5a6464 ok = True try: fd.write(write_value.e... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | EliahKagan |
| hostname | github.com |
| expected-hostname | github.com |
| None | e25f416bb6d8a5f8624aad6cebc375ab2c50ac58f2175f32a7093325e66e5515 |
| turbo-cache-control | no-preview |
| go-import | github.com/gitpython-developers/GitPython git https://github.com/gitpython-developers/GitPython.git |
| octolytics-dimension-user_id | 503709 |
| octolytics-dimension-user_login | gitpython-developers |
| octolytics-dimension-repository_id | 1126087 |
| octolytics-dimension-repository_nwo | gitpython-developers/GitPython |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 1126087 |
| octolytics-dimension-repository_network_root_nwo | gitpython-developers/GitPython |
| turbo-body-classes | logged-out env-production page-responsive |
| disable-turbo | false |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | 32212b8b3bddd6432b3b35d27c050b1c22bd8cca |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width