in reply to Seg fault at dSP in Perl XS

You have a big problem. A perl interp is not thread safe with itself. I could tell you to use to just use PERL_SET_CONTEXT to move the perl interp pointer between threads, but you will then probably have random panics and bizzare type errors. I suggest a pure C callback system with a struct with a mutex in it, that is shared between your SO's threads and your perl interp's thread. Your SO thread will run, get the lock, write whatever into the struct, release the lock, then your XS code will obtain the lock on the struct (or block on the lock of the SO side), read the contents, release the lock. The design won't work if the C caller requires some kind of data that must be calculated in the C callback, and can't sanely be done in pure C with a pile of flags and option codes in a struct.

BrowserUK's solution is one choice, its too adventurous for my taste, freezing the perl interp, putting it in a pool of some kind, grabbing it for your library's thread to use, run some Perl code, then releasing it back to the pool, and eventually the original XS func will take the interp from the pool and return it back to the original Perl thread. I don't know if sleep() is the "correct" way to freeze the perl interp or if perl's sleep op is rated for reenterancey. To use sleep to freeze the interp, you would be depending on the internal implementation of perl safe/deferred signals at the moment. I think a dedicated XS func to freeze the interp and release the interp to be locked by the pool of threads is safer.

My opinion is there are no problems that make it impossible to use your library, its just very difficult for someone isn't familiar with XS, the perl interp, and OS multithreading/thread safety. You should also have a -Od/-DDEBUGGING compiled perl interp, a C debugger, and full symbols for that debugger. Be sure to use " #define PERL_NO_GET_CONTEXT " and use aTHX/aTHX_ and pTHX/pTHX_ and " tTHX my_perl;" to declare but not initialize a my_perl pointer. A dTHX will declare and initialize. Use your C compiler and a C code fomatter to look at the post-processed output of your code. Once you see the post-processor code, you will get a better idea what going on. You have to create a my_perl pointer AND use PERL_SET_CONTEXT. Both are required. Some parts of the perl interp pass the my_perl pointer as a c parameter, others parts of the perl interp use dTHX to fetch it from, atleast on Windows its called Thread Local Storage. No idea what perl uses on Unix for PERL_SET_CONTEXT. Remember at the end of your C callback in the library's thread, to do "PERL_SET_CONTEXT(NULL);" to make sure that there is no accident of making a callback into the interp while the interp is executing other code. Also Browser UK's solution doesn't scale well if you have dozens of threads, and alot of synchronous I/O or long (many millsecs) Perl language code to run. Your library will start to slow down because the C callbacks block on the lock for the single perl interp. Remember your library probably creates many OS threads for a good reason. If push this design too far, you will have effectively made your library single threaded. If your run into the limitation of having only 1 perl interp in the process, you have to create more. I've never seen C code that made a pool of perl interps that get borrowed randomly by random OS threads, but it should be possible.

Without seeing code, its difficult to help you with anything else but generalities.

Replies are listed 'Best First'.
Re^2: Seg fault at dSP in Perl XS
by sohan123 (Novice) on May 31, 2012 at 09:08 UTC
    Thanks alot BrowserUK and bulk88. BrowserUK's solution worked for me.