Re: Inline C: using stderr segfaults? (A solution)
by BrowserUk (Patriarch) on Nov 05, 2007 at 13:52 UTC
|
#include <stdarg>
void eprintf( const char *template, ... ) {
va_list ap;
va_start( ap, template );
vfprintf( stderr, template, ap );
va_end( ap );
}
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.
| [reply] [d/l] |
Re: Inline C: using stderr segfaults?
by mwah (Hermit) on Nov 05, 2007 at 12:26 UTC
|
Microsoft (R) 32-bit C/C++ Standard Compiler Version 13.00.9466 for 80x86
Maybe thats the point. Wasn't Activestate Perl build with the 12.xx version? Using your code, I got a clean run under AS 822 and
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86where it says:
Got:'fred'
77c2fcc0
Got:'fred'
Regards
mwa
| [reply] [d/l] |
|
|
You may well be right I fear, though this is the first time I have encountered a problem with the apparent mismatch. I tracked the error using a debugger to an Rtl CriticalSection function.
And the following version which crudely approximates using fprintf() runs fine:
#! perl -slw
use strict;
use Inline 'FORCE';
use Inline C => 'DATA', NAME => 'IC_junk1', CLEAN_AFTER_BUILD => 0;
test( 'fred' );
test2( 'fred' );
__DATA__
__C__
//#include <stdio.h>
void test ( char* text ) {
printf( "Got:'%s'\n", text );
printf( "%x\n", stderr );
}
void test2 ( char* text ) {
char buf[ 255 ];
sprintf( buf, "%s", text );
fputs( stderr, buf );
}
So it does look like some difference in the CRTs that is responsible. I'd swear that I've used fprintf() from inline C before, but a quick scan of my files revealed none and I found a couple that called Perl_warn(), so maybe I encountered and worked around it some time ago and forgot.
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.
| [reply] [d/l] |
|
|
So it does look like some difference in the CRTs that is responsible
It need not exactly be a "difference in the CRTs". When perl uses one CRT and the compiler uses a different CRT, you can get situations where something (eg a handle) is created by one CRT and then passed to the other CRT (which knows nothing about that handle, and segfaults).
This problem arises when you try to build Win32::SharedFileOpen - which is the only example I know of, btw. A little surprising (at first glance) is the fact that you can build Win32::SharedFileOpen on ActivePerl using the MinGW compiler ... but it's not really surprising, because MinGW uses the same CRT as ActivePerl.
Fwiw, the original script you provided builds fine for me on ActivePerl using MinGW.
Cheers, Rob
| [reply] |
|
|
Re: Inline C: using stderr segfaults?
by parv (Parson) on Nov 05, 2007 at 10:10 UTC
|
Just a data point: no problem here (FreeBSD 6-STABLE/i386 32 bit, gcc 3.4.6, Perl 5.8.8 (64-bit integer support), Inline::C 0.44) with test2 call. | [reply] [d/l] |
Re: Inline C: using stderr segfaults?
by moritz (Cardinal) on Nov 05, 2007 at 10:14 UTC
|
Works for me as well, perl 5.8.8, gcc 4.1.2, on Debian GNU/Linux "Etch", 32 bit. | [reply] |
Re: Inline C: using stderr segfaults?
by salva (Canon) on Nov 05, 2007 at 16:16 UTC
|
another possibility is perl redefining fprintf or stderr with some macro.
Add to your script
use Inline Config => FORCE_BUILD => 1,
CLEAN_AFTER_BUILD => 0,
BUILD_NOISY => 1;
to see what Inline is doing and then rerun the compilation step manually adding the option to only perform the C preprocessing (for instance, with gcc it is -E).
Then, on the preprocessor output, look for test2 and check the fprintf expansion.
| [reply] [d/l] [select] |
|
|
fprintf(
(
*(
*Perl_IStdIO_ptr(
(
( PerlInterpreter *)Perl_get_context()
)
)
)->pStderr
)
(
(
*Perl_IStdIO_ptr(
(
( PerlInterpreter* ) Perl_get_context()
)
)
)
),
"Get:'%s'\n", text
);
And if you can make sense of that your a better man that I.
It's no wonder function calls are slow in perl. Some single lines of XS code end up calling Perl_get_context() 7 or 8 times. There has to be a better way.
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.
| [reply] [d/l] [select] |
|
|
(*Perl_IStdIO_ptr(((PerlInterpreter *)Perl_get_context())))->pStderr
returns a function pointer, and the next parenthesized expresion,
((*Perl_IStdIO_ptr((( PerlInterpreter* ) Perl_get_context()))))
are the arguments for calling that function.
It's no wonder function calls are slow in perl. Some single lines of XS code end up calling Perl_get_context() 7 or 8 times. There has to be a better way
Well, yes, there is a better way!... at least for XS, I don't know about Inline::C, though probably not.
You have to start your XS files defining the macro ...
#define PERL_NO_GET_CONTEXT 1
... and then pass the Perl context manually from function to function using pTHX, aTHX, pTHX_ and aTHX_. See perlguts for the details.
| [reply] [d/l] [select] |
|
|
|
|