OlegG has asked for the wisdom of the Perl Monks concerning the following question:

Crash occures only on Windows.
Here is a simple example

My.xs
#include <pthread.h> #include "EXTERN.h" #include "perl.h" #include "XSUB.h" #include "ppport.h" void *thread(void *arg) { char *msg = (char*)arg; printf("thread: %s\n", msg); free(msg); return NULL; } MODULE = My PACKAGE = My void test_thread(char *msg) PPCODE: char *thread_arg = malloc((strlen(msg)+1)*sizeof(char)); strcpy(thread_arg, msg); pthread_t tid; pthread_create(&tid, NULL, thread, (void*)thread_arg); void *rv; pthread_join(tid, &rv);


lib/My.pm
package My; use strict; use XSLoader(); our $VERSION = 0.01; XSLoader::load('My', $VERSION); 1;


Makefile.PL
use ExtUtils::MakeMaker; WriteMakefile( NAME => 'My', VERSION_FROM => 'lib/My.pm', LIBS => ['-lpthread'], );


t.pl
use blib; use My; My::test_thread("Just another XS hacker");


This works on Linux and crashes on Windows. If I'll comment free(msg) it will also work on Windows.
What's wrong here?

UPD:
All files of the example in one place: https://github.com/olegwtf/sandbox/tree/master/xs-free-windows-problem

Replies are listed 'Best First'.
Re: XS: free() outside of the main thread causes crash on Windows
by BrowserUk (Patriarch) on Sep 25, 2014 at 07:01 UTC
    This works on Linux and crashes on Windows.

    I'm very surprised that it even builds on Windows given that Windows doesn't support pthreads.

    How is it resolving #include <pthread.h>; and therefore pthread_create() & pthread_join()?


    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.

        I strongly suggest that you should compile your code with /E or equivalent to produce the post-preprocessor code and take a look at what is actually being call for malloc() and free(); because it almost certainly isn't the appropriate CRT routines.


        With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.
        Have you heard of perlclib? It advocates using Newx() and Safefree() instead of malloc/free
      mingw as always
      citrusperl\mingw\mingw32\pthreads-win32\i686-w64-mingw32\lib\libpthrea +d.a citrusperl\mingw\mingw32\pthreads-win32\i686-w64-mingw32\include\pthre +ad.h
Re: XS: free() outside of the main thread causes crash on Windows
by syphilis (Archbishop) on Sep 25, 2014 at 08:43 UTC
    For standalone testing purposes, you can run this as an Inline::C script:
    use strict; use warnings; use Inline C => Config => USING => 'ParseRegExp', BUILD_NOISY => 1, ; use Inline C => <<'EOC'; #include <pthread.h> void *thread(void *arg) { char *msg = (char*)arg; printf("thread: %s\n", msg); free(msg); return NULL; } void test_thread(char *msg) { char *thread_arg = malloc((strlen(msg)+1)*sizeof(char)); strcpy(thread_arg, msg); pthread_t tid; pthread_create(&tid, NULL, thread, (void*)thread_arg); void *rv; pthread_join(tid, &rv); } EOC test_thread("Just another XS hacker");
    Like you say, that crashes on Windows unless "free(msg;" is commented out. At least that's what I'm seeing on Strawberry-5.20.0.
    But it looks to me that the memory for "msg" has not been dynamically allocated, and therefore shouldn't be set free().

    If you want to free() the memory what was malloc()'ed you can free(thread_arg); at the end of the test_thread() sub.
    However, I'm guessing that defeats the purpose of the demo. (Sorry - complete threads-idiot, here. Does the memory have to be free()'d in the thread sub ?)

    Cheers,
    Rob
Re: XS: free() outside of the main thread causes crash on Windows
by OlegG (Monk) on Sep 25, 2014 at 11:46 UTC
    Re: XS: free() outside of the main thread causes crash on Windows
    by ikegami (Patriarch) on Sep 25, 2014 at 14:25 UTC

      XS is Perl-aware glue, and as such, Perl redefines certain functions to Perl-aware functions.

      I'd start by separating your Perl-incompatible stuff (non-Perl threads, and the non-Perl memory allocation) from XS. A separate file would be good, but the following might suffice.

      #include <pthread.h> void *thread(void *arg) { char *msg = (char*)arg; printf("thread: %s\n", msg); free(msg); return NULL; } void test_thread(const char *msg) { char *thread_arg = malloc((strlen(msg)+1)*sizeof(char)); strcpy(thread_arg, msg); pthread_t tid; pthread_create(&tid, NULL, thread, (void*)thread_arg); void *rv; pthread_join(tid, &rv); } #include "EXTERN.h" #include "perl.h" #include "XSUB.h" #include "ppport.h" MODULE = My PACKAGE = My void test_thread(const char *msg)

      Note that mid-block variable declarations (like thread_arg, tid and rv in your code, and the latter two in mine) aren't legal C89 which Perl supports. Of course, it doesn't mean you have to support it.