in reply to SOLVED: XS: Passing an external library's function a Perl XS callback

I'm surprised no-one has commented on this yet: are you really attempting to call perl code from an ISR (interrupt service routine)? Perl does allow "PERL_SIGNALS=unsafe", but generally, signal handling is deferred for good reasons.

What sort of code do you need to invoke from an interrupt handler? Can't you just use the regular dispatch via $SIG{USR1} or something?

Replies are listed 'Best First'.
Re^2: XS: Passing an external library's function a Perl XS callback
by stevieb (Canon) on Aug 15, 2016 at 20:29 UTC

    Essentially, an external program is handling the interrupts within threads... I just want to be able to have user-generated perl code executed when the interrupt is triggered.

    I've found that the problem isn't necessarily with the wiringPi software. I've recreated the issue without external libraries. The problem seems to be with threads. The following works fine, until I uncomment the XS code within the wrapper() function...

    use warnings; use strict; use Inline (C => 'DATA', libs => '-lpthread'); create_thread('blah'); sub blah { print "perl callback\n"; } __DATA__ __C__ #include <pthread.h> #include <stdio.h> #include <stdlib.h> void wrapper(void *sub_name_ptr){ char *sub_name = (char *)sub_name_ptr; printf("threaded ok, sub: %s\n", sub_name); /* dSP; PUSHMARK(SP); PUTBACK; call_pv(sub_name, G_DISCARD|G_NOARGS); FREETMPS; LEAVE; */ return NULL; } int create_thread(char *subname){ pthread_t sub_thread; if(pthread_create(&sub_thread, NULL, wrapper, subname)) { fprintf(stderr, "Error creating thread\n"); return 1; } if(pthread_join(sub_thread, NULL)) { fprintf(stderr, "Error joining thread\n"); return 2; } return 0; }

      Under threads, perl code needs the appropriate context. If you callback to code referenced from one thread whilst running under another, you will have the wrong context and crash.

      Read down from here, it may help. There is lots of good information, but it evolves out over a long back&forth thread.


      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". I knew I was on the right track :)
      In the absence of evidence, opinion is indistinguishable from prejudice.

        Thanks BrowserUK!!!!! That's it!!

        Just before I came back and checked here, I was finding that it was the instance of the interpreter so I was just about to head down that path. You made it extraordinarily easy for me. I just had to add two lines (the PerlInterpreter line and the PERL_SET_CONTEXT line. Here's the working pthread test script. After I clean up my original code that started this thread, I'll update the thread.

        use warnings; use strict; use Inline (C => 'DATA', libs => '-lpthread'); create_thread('blah'); sub blah { print "perl callback\n"; } __DATA__ __C__ #include <stdio.h> #include <pthread.h> PerlInterpreter *saved; void wrapper(void *sub_name_ptr){ char *sub_name = (char *)sub_name_ptr; PERL_SET_CONTEXT(saved); printf("threaded ok, sub: %s\n", sub_name); dSP; PUSHMARK(SP); PUTBACK; call_pv(sub_name, G_DISCARD|G_NOARGS); FREETMPS; LEAVE; return NULL; } int create_thread(char *subname){ pthread_t sub_thread; if(pthread_create(&sub_thread, NULL, wrapper, subname)) { fprintf(stderr, "Error creating thread\n"); return 1; } if(pthread_join(sub_thread, NULL)) { fprintf(stderr, "Error joining thread\n"); return 2; } return 0; }