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

Change proposal for win32/vmem.h #16351

Closed
p5pRT opened this issue Jan 7, 2018 · 4 comments
Closed

Change proposal for win32/vmem.h #16351

p5pRT opened this issue Jan 7, 2018 · 4 comments

Comments

@p5pRT
Copy link

@p5pRT p5pRT commented Jan 7, 2018

Migrated from rt.perl.org#132690 (status was 'open')

Searchable as RT132690$

@p5pRT
Copy link
Author

@p5pRT p5pRT commented Jan 7, 2018

From keuchel@rainer-keuchel.de

I had a problems with Inline​::CPP on Windows/MingW.

DLLs built with Inline​::CPP use msvcrt malloc/free.

When USE_LINKED_LIST is defined in vmem.h
then memory from a DLL built by Inline​:CPP cannot be freed
and a SEGV is generated.

I would suggest to check if the pointer to free belongs to the process heap
and free it accordingly with free().

With this change everything is fine..

void VMem::Free(void* pMem)
{
#ifdef _USE_LINKED_LIST
    if (pMem) {
      size_t s;
      HANDLE hHeap;

      PMEMORY_BLOCK_HEADER ptr =
(PMEMORY_BLOCK_HEADER)(((char*)pMem)-sizeof(MEMORY_BLOCK_HEADER));

      if (ptr->owner != this) {

*   // can be block from msvcrt malloc when using Inline::CPP!**
**    hHeap = GetProcessHeap();**
**    s = HeapSize(hHeap, 0, pMem);**
**
**    if(s == (size_t) -1)**
**      {**
**        dTHX;**
**        Perl_warn(aTHX_ "ptr %p is not alloc'ed from msvcrt malloc",
pMem);**
**      }**
**    else**
**      {**
**        //dTHX;**
**        //Perl_warn(aTHX_ "ptr %p is alloc'ed from msvcrt malloc",
pMem);**
**        m_pfree(pMem);**
**        return;**
**      }**
***

        if (ptr->owner) {
#if 1
        dTHX;
            int *nowhere = NULL;
            Perl_warn(aTHX_ "Free to wrong pool %p not
%p",this,ptr->owner);
                *nowhere = 0; /* this segfault is deliberate,
                                 so you can see the stack trace */
#else
                ptr->owner->Free(pMem);
#endif
        }
        return;
        }
    GetLock();
    UnlinkBlock(ptr);
    ptr->owner = NULL;
    m_pfree(ptr);
    FreeLock();
    }
#else
    m_pfree(pMem);
#endif
}

@p5pRT
Copy link
Author

@p5pRT p5pRT commented Jan 10, 2018

From @bulk88

On Sun, 07 Jan 2018 10​:48​:37 -0800, keuchel@​rainer-keuchel.de wrote​:

I had a problems with Inline​::CPP on Windows/MingW.

DLLs built with Inline​::CPP use msvcrt malloc/free.

When USE_LINKED_LIST is defined in vmem.h
then memory from a DLL built by Inline​:CPP cannot be freed
and a SEGV is generated.

I would suggest to check if the pointer to free belongs to the process heap
and free it accordingly with free().

With this change everything is fine..

Calling HeapSize on random pointers, with there being NO guarantee the pointer was allocated by the kernel32.dll heap allocater isn't safe. While modern (>= Vista or XP) checksum/XOR the 8/16 byte malloc header before pointer to detect corruption, that is implementation specific and undependable.

I think your problem is Inline​::CPP doesnt do a #include "XSUB.h", so the #define free(x) never happens that most Win32 XS code has that maps the free token to perl's own allocator. It is a long running problem on Win32 perl. I think the original reason for hooking free() in XS code was for ithread/psuedo-fork cleanup/anti-leaking on psuedo-proc exit so perl can cleanly free "global" pointers from C-ish (not using perl data structures) XS code that keep things allocated forever because it assumes the OS will clean it up on process exit (but perl has psuedo-procs). That linked list code also smoothes over any P5P memory leaks that perl_destruct doesn't free by accident.

There is yet another problem about multiple CRTs in a process and they generate their own Kernel32 Heap objects/pools too, they dont use heap returned by GetProcessHeap. Use VMMap tool on a perl process, click orange Heap, then in the bottom there will be atleast 2 heap IDs (AKA pools), one is GetProcessHeap, other is CRT specific and Perl uses that. If you wind up in CRT hell, each new CRT in the process will make its own pool. Many 3rd party and MS DLLs like to make their Heap pools too. Some C libraries like to add their own header to an object/allocation they give you and they dont give you a pointer to the start of the allocation but a pointer to somewhere inside the allocation. These libraries also tell you to free the resource ONLY by using their functions, not a generic ISO C free().

You need to figure out what is going on with the headers, make a .i file, run it through gnu indent, and figure out if your Inline​::CPP code is perl/XS aware or not and what is the final C symbol name of the callsite of that free() in your code. "NO_XSLOCKS" is the define that usually turns off perl hooking C std lib functions.

--
bulk88 ~ bulk88 at hotmail.com

@p5pRT
Copy link
Author

@p5pRT p5pRT commented Jan 10, 2018

The RT System itself - Status changed from 'new' to 'open'

@toddr
Copy link
Member

@toddr toddr commented Feb 11, 2020

Barring a further response from the reporter, I'm closing this ticket for now.

@toddr toddr closed this as completed Feb 11, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants