Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

return-in-finally in multiprocessing/connection.py #131233

Closed
iritkatriel opened this issue Mar 14, 2025 · 2 comments
Closed

return-in-finally in multiprocessing/connection.py #131233

iritkatriel opened this issue Mar 14, 2025 · 2 comments
Labels
stdlib Python modules in the Lib dir topic-multiprocessing

Comments

@iritkatriel
Copy link
Member

iritkatriel commented Mar 14, 2025

https://github.com/python/cpython/blob/7fd61607cd28ec466717c78adfb1eb5b63add1f0/Lib/multiprocessing/connection.py#L330C1-L340C68

This is clearly a bug, because the except: clause contains a naked raise, i.e., asks for the exception to propagate on. But the return in finally swallows that exception.

                    try:
                              ...
                    except:
                        ov.cancel()
                        raise
                    finally:
                        nread, err = ov.GetOverlappedResult(True)
                        if err == 0:
                            f = io.BytesIO()
                            f.write(ov.getbuffer())
                            return f
                        elif err == _winapi.ERROR_MORE_DATA:
                            return self._get_more_data(ov, maxsize)

Linked PRs

@iritkatriel iritkatriel added the type-bug An unexpected behavior, bug, or error label Mar 14, 2025
@iritkatriel iritkatriel changed the title return-in-finally but in multiprocessing/connection.py return-in-finally bug in multiprocessing/connection.py Mar 14, 2025
@iritkatriel iritkatriel added the stdlib Python modules in the Lib dir label Mar 14, 2025
@ncoghlan
Copy link
Contributor

I don't believe this is actually a bug.

The logic as written:

  • If an exception occurs while waiting for overlapped IO, cancel the overlapped IO request
  • Regardless of whether an exception occurred while waiting or not, get the overlapped IO result
  • If the IO operation was successful (in one of two possible ways), return a BytesIO instance containing the received data, even if an exception occurred while waiting for the operation
  • If the IO operation wasn't successful, re-raise any raised exception

While it's a genuinely cryptic way of writing the code, I'm not seeing an immediately obvious way to rewrite it to eliminate the return-in-finally without duplicating the Win32 overlapped IO result and error code checking logic.

@iritkatriel
Copy link
Member Author

iritkatriel commented Mar 14, 2025

Yes, I see - the return is conditional so it's possible that what you wrote was the intention.

Would this be a way to rewrite it?

                sentinel = object()
                return_value = sentinel
                try:
                    try:
                        if err == _winapi.ERROR_IO_PENDING:
                            waitres = _winapi.WaitForMultipleObjects(
                                [ov.event], False, INFINITE)
                            assert waitres == WAIT_OBJECT_0
                    except:
                        ov.cancel()
                        raise
                    finally:
                        nread, err = ov.GetOverlappedResult(True)
                        if err == 0:
                            f = io.BytesIO()
                            f.write(ov.getbuffer())
                            return_value = f
                        elif err == _winapi.ERROR_MORE_DATA:
                            return_value = self._get_more_data(ov, maxsize)
                except:
                    if return_value == sentinel:
                        raise

                if return_value != sentinel:
                    return return_value

iritkatriel added a commit to iritkatriel/cpython that referenced this issue Mar 18, 2025
iritkatriel added a commit to iritkatriel/cpython that referenced this issue Mar 21, 2025
@iritkatriel iritkatriel changed the title return-in-finally bug in multiprocessing/connection.py return-in-finally in multiprocessing/connection.py Mar 21, 2025
@iritkatriel iritkatriel removed the type-bug An unexpected behavior, bug, or error label Mar 21, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
stdlib Python modules in the Lib dir topic-multiprocessing
Projects
None yet
Development

No branches or pull requests

3 participants