Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?
 
PerlMonks  

[Win32] pthreads and memory allocation

by syphilis (Canon)
on Nov 22, 2011 at 02:50 UTC ( #939358=perlquestion: print w/ replies, xml ) Need Help??
syphilis has asked for the wisdom of the Perl Monks concerning the following question:

Hi,

Here is the Inline::C demo, based on the wikipedia example program. It runs fine for me on Cygwin, but never gets beyond the malloc call on native Win32 - where I'm using perl-5.12.0 and mingw.org's port of gcc-4.5.2 (which ships with the pthread library included).

Note that I'm allocating with 'malloc'. Re-allocating with 'realloc' produces the same problem, as does using 'Newx' or 'Renew' instead of the standard C functions.
use warnings; use Inline C => Config => LIBS => '-lpthread', BUILD_NOISY => 1; use Inline C => <<'EOC'; #include <pthread.h> #include <stdio.h> #include <stdlib.h> #include <assert.h> #include <malloc.h> void *TaskCode(void *argument) { int tid; char * s; tid = *((int *) argument); printf("thread %d: calling malloc\n", tid); s = (char*) malloc(100); printf("thread %d: malloc called\n", tid); return NULL; } void demo (int NUM_THREADS) { pthread_t threads[NUM_THREADS]; int thread_args[NUM_THREADS]; int rc, i; /* create all threads */ for (i=0; i<NUM_THREADS; ++i) { thread_args[i] = i; printf("In demo: creating thread %d\n", i); rc = pthread_create(&threads[i], NULL, TaskCode, (void *) &threa +d_args[i]); assert(0 == rc); } /* wait for all threads to complete */ for (i=0; i<NUM_THREADS; ++i) { rc = pthread_join(threads[i], NULL); assert(0 == rc); } exit(EXIT_SUCCESS); } EOC demo(2);
As is, on Win32 that outputs:
In demo: creating thread 0 In demo: creating thread 1 thread 0: calling malloc thread 1: calling malloc
at which point it crashes. (Irrespective of how many threads I specify it always crashes when *all* threads have reached the stage of having to allocate the memory.)

If I comment out the s = (char*) malloc(100); it outputs the expected:
In demo: creating thread 0 In demo: creating thread 1 thread 0: calling malloc thread 0: malloc called thread 1: calling malloc thread 1: malloc called
Does anyone have some advice as to how I might successfully allocate memory inside the 'TaskCode' function on Win32 ?

(I'm also interested to hear any theories that explain the behaviour I'm seeing.)

Cheers,
Rob

Comment on [Win32] pthreads and memory allocation
Select or Download Code
Re: [Win32] pthreads and memory allocation
by ikegami (Pope) on Nov 22, 2011 at 03:19 UTC

    malloc can be one of many memory allocation system inside of XS, and it's not necessarily the same as the one pthreard was compiled with. I suspect your problems are related to that.

    Write C in C, not in XS. Use XS as the glue.

Re: [Win32] pthreads and memory allocation
by BrowserUk (Pope) on Nov 22, 2011 at 06:06 UTC
    at which point it crashes. (Irrespective of how many threads I specify it always crashes when *all* threads have reached the stage of having to allocate the memory.)

    Probably none of the started threads will get any time slice until your main thread enters the join wait state. Try adding a 1 second sleep inside the loop and it will probably crash as soom as the first one tries to run.


    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.
      Yes, it then crashes as soon as the 1st thread tries to malloc. Then, having cleared the popup, I get some more output indicating that the 2nd thread got as far as the malloc, too. But it never gets any further than that.

      Cheers,
      Rob

        I think that the problem is likely that malloc has been redefined by the Perl/XS headers and the Perl code that gets called is trying to access the perl thread context for the "current" thread. Which of course doesn't exist because the thread was not created by Perl.

        See Re: Win32::Internet crash, XS, callbacks, perl stack & context, windows api, interpreter thread safety, 1 perl, many C threads by windows for previous related discussion on the problem.

        See also Perl crash during perl_clone for a long and twisty thread where I worked through the same problem to a successful conclusion.


        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.

        Another thought. If you add #undef malloc just prior to your use of malloc, you may find that the code will run without immediately crashing. But I make no claim that you won't run into similar problems later on.


        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.
Re: [Win32] pthreads and memory allocation
by Marshall (Prior) on Nov 22, 2011 at 06:20 UTC
    I am having trouble understanding even the basics of this C code.
    TaskCode() returns a pointer to anything and accepts a pointer to anything.

    There is nothing returned from this C subroutine,
    void *TaskCode(void *argument).

    tid = *((int *) argument);
    means: argument is "cast" as a pointer to integer.
    Then that result is de-referenced to get the "tid". A **int.

    The OP's code is a memory leak because there is no pointer or other way to use the memory allocated by
    "s = (char*) malloc(100);".

    void *TaskCode(void *argument) { int tid; char * s; tid = *((int *) argument); // tid = **argument; printf("thread %d: calling malloc\n", tid); s = (char*) malloc(100); printf("thread %d: malloc called\n", tid); return NULL; }
    "s" is a memory pointer returned by malloc(). Now a malloc() call should have a conditional statement to see that it actually worked. But the big thing here is that the subroutine TaskCode() returns bullshit. I don't see how "s", the pointer to a new memory allocation of 100 bytes can ever be used outside of TaskCode()

      It's just a demo to illustrate that malloc() causes a crash on Win32 (but not elsewhere, afaik).
      Perhaps I should have declared char * useless_and_pointless; instead of char * s;.

      Now a malloc() call should have a conditional statement to see that it actually worked

      Yes, if you're wanting to make use of the memory that you've requested be allocated, I think that's a good idea. For the purposes of this demo, however, I don't really care whether the malloc succeeds or fails - I just want it to not cause a crash.
      (Besides, on Win32, I'm not even going to see the result of that "conditional statement" because it never gets executed - due to afore-mentioned crash.)

      Similarly, any memory leak is of no concern to me wrt this particular exercise.

      Cheers,
      Rob
        Yes,
        Perhaps I should have declared char * useless_and_pointless; instead of char * s;.

        Yes, I figure that would be correct and I figure that we understand each other.

        The basic issue is: "s = (char*) malloc(100);". "s" is cast as a pointer to a memory address. "s" is guaranteed to point to at least 100 bytes (consecutive).

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://939358]
Approved by Eliya
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others perusing the Monastery: (9)
As of 2014-07-29 16:04 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    My favorite superfluous repetitious redundant duplicative phrase is:









    Results (220 votes), past polls