Skip to content

bpo-37140 ctypes change made clang fail to build #13796

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

Closed
wants to merge 5 commits into from

Conversation

paulmon
Copy link
Contributor

@paulmon paulmon commented Jun 4, 2019

Passing structs on Linux follows a different convention than Windows.
Add ifdefs to keep both conventions.

@zooba, @zware

https://bugs.python.org/issue37140

@paulmon
Copy link
Contributor Author

paulmon commented Jun 4, 2019

If I revert the Windows code to match the previous code then test_pass_by_value (ctypes.test.test_structures.StructureTestCase) fails, hence the ifdefs.

It seems likely that there is a still a bug on Windows if self->b_ptr contains a ctypes Structure with a destructor that frees resources because the Windows code uses memcpy to do a copy of the struct data without refcounting. This can leave a dangling pointer as in the clang binding example which throws an exception on the second free.

see
memcpy(new_ptr,` self->b_ptr, self->b_size);

@csabella csabella requested review from encukou and zooba June 4, 2019 11:28
@vstinner
Copy link
Member

vstinner commented Jun 4, 2019

It would be great to be able to write a reproducer and then convert it into a proper unit test.

@paulmon
Copy link
Contributor Author

paulmon commented Jun 4, 2019

It seems like it's not possible to have pass-by-value make a copy and also not duplicate pointers in structs. When the struct has a destructor as in this unittest the copy causes the pointer to be freed twice which causes an access violation.

Is it wrong to make a copy?

Is there a way to modify the struct implementation so that it doesn't cause an exception to be thrown when passed by value?

@paulmon paulmon changed the title bpo-37140 restore union parameter passing code Linux bpo-37140 restore struct/union parameter passing code Linux Jun 5, 2019
@paulmon
Copy link
Contributor Author

paulmon commented Jun 11, 2019

I did some reading about parameter passing and it's still not clear to me whether https://bugs.python.org/issue37140 is a bug in CPython or whether the clang bindings were relying on incorrect parameter passing behavior to work.

The change in the PR restores the previous behavior where Windows and non-Windows builds pass structs differently.

@@ -432,6 +433,24 @@ StructUnionType_paramfunc(CDataObject *self)
parg->value.p = copied_self->b_ptr;
parg->size = copied_self->b_size;
parg->obj = (PyObject *)copied_self;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this needs to be PyTuple_Pack(2, self, copied_self) for the case where we have both, along with correct refcounting. The rest of the change to this file should be safe to undo.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@zooba, are you saying that the ref counting in the test code needs fixed (and the clang bindings code)?

@paulmon paulmon changed the title bpo-37140 restore struct/union parameter passing code Linux bpo-37140 ctypes change made clang fail to build Jul 11, 2019
@paulmon
Copy link
Contributor Author

paulmon commented Aug 12, 2019

@zooba @encukou
This passes the test now.
Does this look like the right thing to do?

@vstinner
Copy link
Member

I cannot explain why, but this change creates a huge memory leak. It seems like copied_self is no longer destroyed. I guess that it's reference counter no longer reach zero, which works around the bug. This change doesn't fix the root issue: if copied_self would be destroyed, the structure finalizer (del) would still be caled twice.

I wrote a different fix PR #15612 which fix https://bugs.python.org/issue37140 regression and does not introduce a memory leak.

Copy link
Member

@vstinner vstinner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR leaks memory. I suggest to use my fix PR #15612 instead.

@bedevere-bot
Copy link

A Python core developer has requested some changes be made to your pull request before we can consider merging it. If you could please address their requests along with any other requests in other reviews from core developers that would be appreciated.

Once you have made the requested changes, please leave a comment on this pull request containing the phrase I have made the requested changes; please review again. I will then notify any core developers who have left a review that you're ready for them to take another look at this pull request.

@vstinner
Copy link
Member

I merged my PR #15612, but thanks for this PR: it helped me to understand the root issue!

@vstinner vstinner closed this Aug 30, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants