Mailing List Archive

xsubpp/Makemaker/Dynaloader Suggestion
Recently I had someone report to me what they though was a bug with some
of my code, but when I tracked it down it turned out that the wrong
code was being dynamically loaded.

The module in question was Socket, but it could have been any other
module just as easy. In my code I did

use Socket 1.3;

which did not fail as the installed .pm file was version 1.3. However I can
only assume that the network contained multiple architectures and Socket v1.3
was only installed on one.

My suggestion is that Dynaloader::bootstrap do a similar thing to Exporter
and accept a version string as an optional argument and die if it
does not match exactly.

Of course there is the question of how do we go about doing this. My suggestion
to this would be to have xsubpp add the followinf line to the boot code
of every module

sv_setpv(perl_get_sv("$Module_cname::XS_VERSION",1),XS_VERSION);

and MakeMaker to change the definition of DEFINE (or CCCDLFLAGS) to

DEFINE = $att{DEFINE} -DXS_VERSION=\\\"\$(VERSION)\\\"

Dynaloader could then check that $XS_VERSION matches what is required.

Comments ...

Regards,
Graham.


--
Graham Barr <bodg@tiuk.ti.com>
Texas Instruments Ltd.
Re: xsubpp/Makemaker/Dynaloader Suggestion [ In reply to ]
Re: xsubpp/Makemaker/Dynaloader Suggestion [ In reply to ]
Re: xsubpp/Makemaker/Dynaloader Suggestion [ In reply to ]
Re: xsubpp/Makemaker/Dynaloader Suggestion [ In reply to ]
Re: xsubpp/Makemaker/Dynaloader Suggestion [ In reply to ]
Paul Marquess <pmarquess@bfsec.bt.co.uk> writes:
>...
>> My suggestion is that Dynaloader::bootstrap do a similar thing to Exporter
>> and accept a version string as an optional argument and die if it
>> does not match exactly.
>>
>> Of course there is the question of how do we go about doing this. My suggestion
>> to this would be to have xsubpp add the followinf line to the boot code
>> of every module
>>
>> sv_setpv(perl_get_sv("$Module_cname::XS_VERSION",1),XS_VERSION);
>>
>> and MakeMaker to change the definition of DEFINE (or CCCDLFLAGS) to
>>
>> DEFINE = $att{DEFINE} -DXS_VERSION=\\\"\$(VERSION)\\\"
>>
>> Dynaloader could then check that $XS_VERSION matches what is required.
>>
>> Comments ...
>
>Good idea.
>
>Rather than getting DynaLoader::bootstrap to take an optional
>parameter, why not just get bootstrap to always check that $VERSION
>from the .pm file equals XS_VERSION from the .xs file. If one/both
>don't exist it doesn't do the test.
>
>After all it doesn't make sense to have .pm & .xs files which aren't
>the same version number.

I see 2 problems with this.

a) MakeMaker will need to know the VERSION of the pm file when it makes
the .o file

b) a .xs file does not necessarily have a .pm file, as pointed out to me
during a discussion with Nick Ing-Simmons

This is why I thought it was best to link the .o file VERSION with the
distribution VERSION rather than the .pm file

Regards,
Graham.

--
Graham Barr <bodg@tiuk.ti.com>
Texas Instruments Ltd.
Re: xsubpp/Makemaker/Dynaloader Suggestion [ In reply to ]
In <9511271152.AA05096@tiuk.ti.com>
On Mon, 27 Nov 95 11:52:54 GMT
<bodg@tiuk.ti.com> writes:
>Paul Marquess <pmarquess@bfsec.bt.co.uk> writes:
>>Rather than getting DynaLoader::bootstrap to take an optional
>>parameter, why not just get bootstrap to always check that $VERSION
>>from the .pm file equals XS_VERSION from the .xs file. If one/both
>>don't exist it doesn't do the test.
>>
>>After all it doesn't make sense to have .pm & .xs files which aren't
>>the same version number.
>
>I see 2 problems with this.
>
>a) MakeMaker will need to know the VERSION of the pm file when it makes
> the .o file

As I said to Graham this morning recent MM passes -DVERSION anyway,
and most extensions can be contrived to keep them in sync.

>
>b) a .xs file does not necessarily have a .pm file, as pointed out to me
> during a discussion with Nick Ing-Simmons

That is very obscure case (i.e. bootstrap is called from another .pm
file) - we could insist on a (trivial if necessary) .pm file, or
"clever" people which do this can work it out for themselves.

>
>This is why I thought it was best to link the .o file VERSION with the
>distribution VERSION rather than the .pm file

If .pm file has different version then it could pass (optional) arg
to bootstrap.
Re: xsubpp/Makemaker/Dynaloader Suggestion [ In reply to ]
Nick Ing-Simmons <nik@tiuk.ti.com> writes:
>In <9511271152.AA05096@tiuk.ti.com>
>On Mon, 27 Nov 95 11:52:54 GMT
> <bodg@tiuk.ti.com> writes:
>>Paul Marquess <pmarquess@bfsec.bt.co.uk> writes:
>>>Rather than getting DynaLoader::bootstrap to take an optional
>>>parameter, why not just get bootstrap to always check that $VERSION
>>>from the .pm file equals XS_VERSION from the .xs file. If one/both
>>>don't exist it doesn't do the test.
>>>
>>>After all it doesn't make sense to have .pm & .xs files which aren't
>>>the same version number.
>>
>>I see 2 problems with this.
>>
>>a) MakeMaker will need to know the VERSION of the pm file when it makes
>> the .o file
>
>As I said to Graham this morning recent MM passes -DVERSION anyway,
>and most extensions can be contrived to keep them in sync.

But this is the VERSION of the distribution not the VERSION of the pm file,
which is the VERSION number avaliable to Dynaloader. A distribution may
contain several .pm/.xs files and a popular method of creating $VERSION is

$VERSION = sprintf("%d.%02d", q$Revision: 1.17 $ =~ /(\d+)\.(\d+)/);

So that the pm file VERSION is the RCS version of that file, so if
a distribution contains multiple .xs/.pm files then each .pm file
may have a different VERSION.

But of course -DVERSION need not be the distriburion VERSION but
could be determined from the .pm file at compile time ???

>>
>>b) a .xs file does not necessarily have a .pm file, as pointed out to me
>> during a discussion with Nick Ing-Simmons
>
>That is very obscure case (i.e. bootstrap is called from another .pm
>file) - we could insist on a (trivial if necessary) .pm file, or
>"clever" people which do this can work it out for themselves.

agreed

>>
>>This is why I thought it was best to link the .o file VERSION with the
>>distribution VERSION rather than the .pm file
>
>If .pm file has different version then it could pass (optional) arg
>to bootstrap.

This is another potential solution to the scenario I described above in that
Dynaloader would only default to $pkg::VERSION if no argument is given.

Regards,
Graham.

--
Graham Barr <bodg@tiuk.ti.com>
Texas Instruments Ltd.
Re: xsubpp/Makemaker/Dynaloader Suggestion [ In reply to ]
Paul Marquess <pmarquess@bfsec.bt.co.uk> writes:
>>
>> Nick Ing-Simmons <nik@tiuk.ti.com> writes:
>> >In <9511271152.AA05096@tiuk.ti.com>
>> >On Mon, 27 Nov 95 11:52:54 GMT
>> > <bodg@tiuk.ti.com> writes:
>> >>Paul Marquess <pmarquess@bfsec.bt.co.uk> writes:
>>
>> ...
>>
>> But of course -DVERSION need not be the distriburion VERSION but
>> could be determined from the .pm file at compile time ???
>
>Reminds me of this way to keep the .pm & .xs versions in sync.
>
>use lib "lib";
>require Net::Ping;
>use ExtUtils::MakeMaker;
>WriteMakefile(NAME => 'Ping',
> DISTNAME => 'Net-Ping',
> VERSION => sprintf("%.2f",$Net::Ping::VERSION),
> dist => {COMPRESS=>'gzip -9f'},
> 'macro' => {CONFIGDEP => 'lib/Net/Ping.pm'}
>
> );

Once again, this is fine if you only have one .pm file in your distribution.
But what if you have more, you need some way of the distribution version
reflecting that any one of the files has changed.

What I meant to say when I wrote

But of course -DVERSION need not be the distriburion VERSION but
could be determined from the .pm file at compile time ???

is that if the distribution contains multiple .pm/.xs files then the
-DVERSION passed to the compiler may need to be different for each
.xs file, ie 'determined from the .pm file at compile time'

>> ...
>>
>> This is another potential solution to the scenario I described above in that
>> Dynaloader would only default to $pkg::VERSION if no argument is given.
>>
>
>Hmm, how about something along these lines:
>
> sub DynaLoader::bootstrap
> {
> my ($PKG) = (caller)[0] ;
> my ($pm_VERSION) ;
> my ($xs_VERSION) ;
> ...
> $pm_VERSION = shift if @_ ;
> $pm_VERSION = ${"${PKG}::VERSION"}
> if !$pm_VERSION and defined ${"${PKG}::VERSION"} ;
>
> boot the .xs file
>
> croak (".pm/.xs mismatch")
> if $pm_VERSION and $xs_VERSION and $pm_VERSION ne $xs_VERSION ;
> }

that is exactly what I was thinking of :-)

Regards,
Graham.

--
Graham Barr <bodg@tiuk.ti.com>
Texas Instruments Ltd.
Re: xsubpp/Makemaker/Dynaloader Suggestion [ In reply to ]
Paul Marquess <pmarquess@bfsec.bt.co.uk> writes:
>> >
>> >Hmm, how about something along these lines:
>
> ...
>
>I have tentatively added your suggested modification to xsubpp. It
>actually looks like this:
>
> /* Create a Perl scalar to hold the module version number. */
> #ifdef XS_VERSION
> sv_setpv(perl_get_sv("${Module_cname}::XS_VERSION",1),XS_VERSION);
> #endif
>
>Another possibility would be to use the VERSION macro in xsubpp, rather
>than create a new one:
>
> sv_setpv(perl_get_sv("${Module_cname}::XS_VERSION",1),VERSION);

Agreed, it should use the VERSION macro, but as I stated in an earlier
message, How should VERSION be derived ?

>I won't release the xsubpp patch for a while, just in case someone
>comes up with a better solution.
>
>I don't think h2xs generates a $VERSION for the .pm file (although it
>does put one in Makefile.PL). Perhaps a patch for h2xs is needed.

probably

Regards,
Graham.

--
Graham Barr <bodg@tiuk.ti.com>
Texas Instruments Ltd.
Re: xsubpp/Makemaker/Dynaloader Suggestion [ In reply to ]
In <9511271653.AA07939@tiuk.ti.com>
On Mon, 27 Nov 95 16:53:49 GMT
<bodg@tiuk.ti.com> writes:
>Paul Marquess <pmarquess@bfsec.bt.co.uk> writes:

>>Another possibility would be to use the VERSION macro in xsubpp, rather
>>than create a new one:
>>
>> sv_setpv(perl_get_sv("${Module_cname}::XS_VERSION",1),VERSION);
>
>Agreed, it should use the VERSION macro, but as I stated in an earlier
>message, How should VERSION be derived ?
>
In C code VERSION is -DVERSION= to Makefile.PL version.
Thus if they don't match you need to use XS_VERSION.
Re: xsubpp/Makemaker/Dynaloader Suggestion [ In reply to ]
Nick Ing-Simmons <nik@tiuk.ti.com> writes:
>In <9511271653.AA07939@tiuk.ti.com>
>On Mon, 27 Nov 95 16:53:49 GMT
> <bodg@tiuk.ti.com> writes:
>>Paul Marquess <pmarquess@bfsec.bt.co.uk> writes:
>
>>>Another possibility would be to use the VERSION macro in xsubpp, rather
>>>than create a new one:
>>>
>>> sv_setpv(perl_get_sv("${Module_cname}::XS_VERSION",1),VERSION);
>>
>>Agreed, it should use the VERSION macro, but as I stated in an earlier
>>message, How should VERSION be derived ?
>>
>In C code VERSION is -DVERSION= to Makefile.PL version.
>Thus if they don't match you need to use XS_VERSION.

Hmm yes, I think I will change my opinion here, the user may want to use
the VERSION macro themselves. So it makes sense to introduce a new macro
XS_VERSION for this purpose.

Regards,
Graham.

--
Graham Barr <bodg@tiuk.ti.com>
Texas Instruments Ltd.
Re: xsubpp/Makemaker/Dynaloader Suggestion [ In reply to ]
From: Graham Barr <bodg@tiuk.ti.com>
>
> Nick Ing-Simmons <nik@tiuk.ti.com> writes:
> >In <9511271653.AA07939@tiuk.ti.com>
> >On Mon, 27 Nov 95 16:53:49 GMT
> > <bodg@tiuk.ti.com> writes:
> >>Paul Marquess <pmarquess@bfsec.bt.co.uk> writes:
> >
> >>>Another possibility would be to use the VERSION macro in xsubpp, rather
> >>>than create a new one:
> >>>
> >>> sv_setpv(perl_get_sv("${Module_cname}::XS_VERSION",1),VERSION);
> >>
> >>Agreed, it should use the VERSION macro, but as I stated in an earlier
> >>message, How should VERSION be derived ?
> >>
> >In C code VERSION is -DVERSION= to Makefile.PL version.
> >Thus if they don't match you need to use XS_VERSION.
>
> Hmm yes, I think I will change my opinion here, the user may want to use
> the VERSION macro themselves. So it makes sense to introduce a new macro
> XS_VERSION for this purpose.

Just as well I didn't post a patch then :-)

There have been a few messages bouncing around, so perhaps it would be
a good idea if I tried to summarise the current state of play.

The perceived problem:

There is no automatic mechanism to detect a mismatch in the version
numbers of a .pm & .o file at run time.

Issues:

1. Although there are VERSION strings available to both the .pm
file and the .xs file, they may not be the same thing. For
example, the .pm VERSION might actually be an RCS/SCCS id and/or
the .xs VERSION might be a package version.

2. To counter 1, there will be a large class of modules where the
two VERSION strings could easily be made the same.

3. There are cases where multiple .pm files (each with separate
VERSION strings) use a single .xs file.

4. There are cases where a .xs file doesn't have an associated .pm
file.


Current Proposed Solution:

* Modify xsubpp to generate a VERSION (and/or XS_VERSION) string
based on either the -DVERSION (or a new -DXS_VERSION) macro.


* Modify DynaLoader to add this logic along these lines:

sub DynaLoader::bootstrap
{
...
my ($PKG) = (caller)[0] ;
my ($pm_VERSION) ;

$pm_VERSION = ${"${PKG}::VERSION"}
if defined ${"${PKG}::VERSION"} ;
$pm_VERSION = shift if @_ ;


boot the .xs file

croak (".pm/.xs mismatch")
if $pm_VERSION and ${"${PKG}::XS_VERSION"} and
$pm_VERSION ne ${"${PKG}::XS_VERSION"} ;
}


* Possibly modify MakeMaker to allow support for XS_VERSION.
XS_VERSION could default to VERSION if not defined in the .PL
file.

Outstanding problems:

1. How to get the XS_VERSION to automatically be the same for a
.pm/.xs pair. I feel that most modules will be the
straightforward one .pm to one .xs pair - it therefore makes
sense then to have the XS_VERSION strings kept in sync as easily
as possible.

2. there are others.


Comments?

Paul
Re: xsubpp/Makemaker/Dynaloader Suggestion [ In reply to ]
> From: pmarquess@bfsec.bt.co.uk (Paul Marquess)
>
> From: Graham Barr <bodg@tiuk.ti.com>
> >
> > Nick Ing-Simmons <nik@tiuk.ti.com> writes:
> > >In <9511271653.AA07939@tiuk.ti.com>
> > >On Mon, 27 Nov 95 16:53:49 GMT
> > > <bodg@tiuk.ti.com> writes:
> > >>Paul Marquess <pmarquess@bfsec.bt.co.uk> writes:
> > >
> > >>>Another possibility would be to use the VERSION macro in xsubpp, rather
> > >>>than create a new one:
> > >>>
> > >>> sv_setpv(perl_get_sv("${Module_cname}::XS_VERSION",1),VERSION);
> > >>
> > >>Agreed, it should use the VERSION macro, but as I stated in an earlier
> > >>message, How should VERSION be derived ?
> > >>
> > >In C code VERSION is -DVERSION= to Makefile.PL version.
> > >Thus if they don't match you need to use XS_VERSION.
> >
> > Hmm yes, I think I will change my opinion here, the user may want to use
> > the VERSION macro themselves. So it makes sense to introduce a new macro
> > XS_VERSION for this purpose.

An interesting thread of messages. (Thanks for the summary Paul! I might not
have bothered to read and reply without it. Too little time right now.)

> Just as well I didn't post a patch then :-)
>
> There have been a few messages bouncing around, so perhaps it would be
> a good idea if I tried to summarise the current state of play.
>
> The perceived problem:
>
> There is no automatic mechanism to detect a mismatch in the version
> numbers of a .pm & .o file at run time.
>
> Issues:
>
> 1. Although there are VERSION strings available to both the .pm
> file and the .xs file, they may not be the same thing. For
> example, the .pm VERSION might actually be an RCS/SCCS id and/or
> the .xs VERSION might be a package version.
>
> 2. To counter 1, there will be a large class of modules where the
> two VERSION strings could easily be made the same.

And I think developers would want them to be the same once standards and
checking mechanisms are defined. The current addhoc arrangements
are probably a reflection of the lack of a standard more than a desire
to do it a particular way.


> 3. There are cases where multiple .pm files (each with separate
> VERSION strings) use a single .xs file.

I think the issue here is more package and module names rather than files.
$VERSION relates to the package name it's defined in and the name of the
module the application 'use's. The Exporter checks for $VERSION in the
package of the same name as the module.

Any VERSION checking code xsubpp adds should be based on the MODULE=Foo
part of the xs declaration lines not the PACKAGE=... part.


> 4. There are cases where a .xs file doesn't have an associated .pm
> file.

Too rare to worry about other than ensuring that whatever we come up with
can be disabled on a per xs file basis.


> Current Proposed Solution:
>
> * Modify DynaLoader to add this logic along these lines:
>
> sub DynaLoader::bootstrap
> {
> ...
> my ($PKG) = (caller)[0] ;
> my ($pm_VERSION) ;
>
> $pm_VERSION = ${"${PKG}::VERSION"}
> if defined ${"${PKG}::VERSION"} ;
> $pm_VERSION = shift if @_ ;
>
> boot the .xs file
>
> croak (".pm/.xs mismatch")
> if $pm_VERSION and ${"${PKG}::XS_VERSION"} and
> $pm_VERSION ne ${"${PKG}::XS_VERSION"} ;
> }

I'd rather the logic went into the BOOT: section of XS files.
It would be faster and give the module developer more choice.

If xsubpp.h automatically #defined XS_VERSION_VAR to be the name of the
$VERSION variable that corresponds to the module, e.g., "Foo::VERSION"
then XSUB.h could simply define macros something like this:

#ifdef XS_VERSION

#define XS_VERSION_MISMATCH \
strNE(XS_VERSION, SvPV(perl_get_sv(XS_VERSION_VAR,GV_ADDWARN)))

#define XS_VERSION_CHECK \
if (XS_VERSION_MISMATCH) croak("...")

#else
#define XS_VERSION_MISMATCH 0
#define XS_VERSION_CHECK
#endif

Then xsubpp could automatically add XS_VERSION_CHECK to the boot section
of all xs files unless a -noversioncheck option was given.

After all the above we're in a position where specifying -DXS_VERSION
to xsubpp automatically enables a default version check that, because
of the GV_ADDWARN, will automatically warn the developer if they have
not defined $VERSION in Foo.pm.

Any developer wanting to avoid all this can simply not specify XS_VERSION
or add -noversioncheck to XSOPTS.

Any developer wanting to implement their own checks or failure modes can
simply add -noversioncheck to XSOPTS in Makefile.PL and then use the
XS_VERSION_MISMATCH macro but not XS_VERSION_CHECK to write their own
code into the BOOT: section.

Comments?


> Outstanding problems:
>
> 1. How to get the XS_VERSION to automatically be the same for a
> .pm/.xs pair. I feel that most modules will be the
> straightforward one .pm to one .xs pair - it therefore makes
> sense then to have the XS_VERSION strings kept in sync as easily
> as possible.

My current thinking is that MakeMaker could effectively grep $modulename.pm
for a string matching

\$VERSION\s*=.*?([\d.]*)

and if found then check it against the VERSION in the Makefile.PL.
This could be done at make-a-distribution-time rather than build-time
since it's a development issue.

Tim.
Re: xsubpp/Makemaker/Dynaloader Suggestion [ In reply to ]
Tim Bunce <Tim.Bunce@ig.co.uk> writes:

...

>Comments?
>
>
>> Outstanding problems:
>>
>> 1. How to get the XS_VERSION to automatically be the same for a
>> .pm/.xs pair. I feel that most modules will be the
>> straightforward one .pm to one .xs pair - it therefore makes
>> sense then to have the XS_VERSION strings kept in sync as easily
>> as possible.
>
>My current thinking is that MakeMaker could effectively grep $modulename.pm
>for a string matching
>
> \$VERSION\s*=.*?([\d.]*)

Here is a routine I use to extract the VERSION of a pm file

sub pm_version {
my $pmfile = shift;
my $version = undef;
local(*PM,$_);

open(PM,$pmfile) || return undef;

while(<PM>) {
if(/^\s*\$VERSION\s*=/) {
$version = eval $_;
last;
}
}

close(PM);

return $version;
}

>and if found then check it against the VERSION in the Makefile.PL.

Why does it need to be checked against VERSION in Makefile.PL ?

>This could be done at make-a-distribution-time rather than build-time
>since it's a development issue.

By 'make-a-distribution-time' do you really mean when you generate the
makefile ?

Regards,
Graham.


--
Graham Barr <bodg@tiuk.ti.com>
Texas Instruments Ltd.