Open FGasper opened 4 years ago
It's not a bug, it was implemented that way on purpose. The whole point of the "Free to wrong pool" error is to tell you that a wrong thread is freeing the memory.
Whether it makes sense or not is a different question. Personally, I'm not familiar enough with that code to have an opinion.
@xenu So are all XSUBs then on the hook to detect when they’re in a pseudo-subprocess and forgo Safefree(), then?
I thought the notion of Safefree() was to abstract away details like that …
Whether it makes sense or not is a different question. Personally, I'm not familiar enough with that code to have an opinion.
I don't think that the people who wrote this still around. I have also been bitten by this, and resorted to using PerlMemShared_malloc and friends, but it's quite unhelpful.
I had assumed it's because perl is using LocalAlloc
, but that doesn't appear to be the case. Quite frankly it rather looks to me like we could remove this logic and nothing stops working.
My second guess is that it prevents memory leaks from pseudo-fork processes to affect the other "processes", but in that case it's really not worth the hassle IMO.
You could try to compile perl with this patch, and see if anything breaks (I suspect not)
Author: Leon Timmermans <fawaka@gmail.com>
Date: Sun Jan 5 16:28:38 2020 +0100
Don't use thread specific memory pools
diff --git win32/vmem.h win32/vmem.h
index 3fd7e169fc..372661944f 100644
--- win32/vmem.h
+++ win32/vmem.h
@@ -22,7 +22,7 @@
#define ___VMEM_H_INC___
#define _USE_MSVCRT_MEM_ALLOC
-#define _USE_LINKED_LIST
+// #define _USE_LINKED_LIST
// #define _USE_BUDDY_BLOCKS
BTW, note that this behavior is not specific to Windows. Unix perls built with -DDEBUGGING
do the same thing (of course, that only affects threads because non-win32 perls don't have pseudoprocesses).
@xenu OK, thank you; that was my next question: whether this avoid-Safefree-if-in-subprocess behavior is specific to win32, or if there’s a broader category of “pseudoprocess-using perls”.
@Leont Off-hand I don’t know how to compile a win32 perl. I’ll look, though. Thank you!
if there’s a broader category of “pseudoprocess-using perls”.
I believe AmigaOS port has pseudoprocesses too, but their implementation is completely separate from the Windows one and I have no idea how it works.
I think this needs documentation rather than a code change. I had thought this was documented, but I don't see anything.
In general if you want memory that isn't tied to the current thread you should be using safesysmalloc()/safesysrealloc()/safesysfree().
I think this needs documentation rather than a code change.
But is there any reason for this behavior? Because quite frankly I've only seen it get in the way of things.
In general if you want memory that isn't tied to the current thread you should be using safesysmalloc()/safesysrealloc()/safesysfree().
@tonycoz These functions are undocumented … should they be added to perlapi/perlclib?
it has bitten me before too (which is why most of Imager avoids the perl headers, since malloc() is redefined to PerlMem_malloc() on Win32).
I guess it depends on why it was added, if we do look at removing it I think it needs to be discussed on the list rather than just in this ticket, so whoever added it has an opportunity to defend it.
@tonycoz These functions are undocumented … should they be added to perlapi/perlclib?
Yes.
On Sun, Jan 05, 2020 at 06:58:56PM -0800, Tony Cook wrote:
I guess it depends on why it was added, if we do look at removing it I think it needs to be discussed on the list rather than just in this ticket, so whoever added it has an opportunity to defend it.
My recollection is that (at the time, at least: 2005), Windows would give a "free to wrong pool" error if memory malloc()ed by one thread was free()d by another thread. Jan DuBois then added a mechanism (by default only enabled on DEBUGGING+PERL_IMPLICIT_CONTEXT builds) that on all platforms recorded thread info with each allocation, and croaked if freed in a different thread - thus helping non-Windows coders like myself from introducing bugs that tested fine on Linux.
The thread where it was introduced is here: http://nntp.perl.org/group/perl.perl5.porters/106649
malloc() on Linux appears thread-safe and includes mechanisms to reduce lock contention. I don't know about other OSes.
-- Justice is when you get what you deserve. Law is when you get what you pay for.
My recollection is that (at the time, at least: 2005), Windows would give a "free to wrong pool" error if memory malloc()ed by one thread was free()d by another thread.
TBH that sounds to me like a case of " No, it is not a compiler error. It is never a compiler error." I really don't believe that malloc
can be so unhelpful without this widely being known and documented. Google tells me msvc malloc isn't thread safe unless one links with the thread-safe c library, which might be the problem observed back then.
My recollection is that (at the time, at least: 2005), Windows would give a "free to wrong pool" error if memory malloc()ed by one thread was free()d by another thread. ...
This is produced by perl, not the underlying malloc() implementation, see https://github.com/Perl/perl5/blob/blead/win32/vmem.h#L199
Both shared and "system" memory end up being allocated/freed with malloc()/free(), with shared memory having a VMem object and each thread having their own VMem objects.
I suspect the intent was to allow fork emulation to clean up all of the (perl) allocated memory from a child thread, but I'm only guessing here.
This comes with a fair amount of overhead on Win32, even on non-debug builds, each memory block has a next and prev pointers for the double-linked list (8-16 bytes), and extra locking (which the underlying malloc() also presumably already does.)
I'm inclined to remove this, but I'd rather not do it blindly.
Description Safefree() in a win32 “subprocess” misbehaves when memory was first allocated in “parent”.
Steps to Reproduce On Win32: Clone https://github.com/FGasper/p5-win32-safefree-bug, then
perl Makefile.PL && gmake && perl -Mblib t\detect_memory_leaks.t
.Expected behavior The test should finish, as it does in Linux. Instead it fails with “Free to wrong pool …”.
Perl configuration Strawberry 5.30.1 64-bit …