Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

caller_cx(0,NULL) returns NULL #15903

Closed
p5pRT opened this issue Mar 2, 2017 · 6 comments
Closed

caller_cx(0,NULL) returns NULL #15903

p5pRT opened this issue Mar 2, 2017 · 6 comments

Comments

@p5pRT
Copy link

p5pRT commented Mar 2, 2017

Migrated from rt.perl.org#130903 (status was 'rejected')

Searchable as RT130903$

@p5pRT
Copy link
Author

p5pRT commented Mar 2, 2017

From @hakonhagland

I am trying to figure out the package name of the caller from an XSUB.
It turns out that Perl C API function caller_cx(0,NULL) does not return
package name of caller, the same way as Perl function caller() does. For
example​:

p.pl​:


#! /usr/bin/env perl
use lib './lib/My/blib/arch';
use lib './lib';
use My​::Caller;
My​::Caller​::test(); #XSUB
My​::Caller​::test2(); #Perl sub

lib/My/Caller.pm​:


package My​::Caller;
require Exporter;
require XSLoader;

our @​ISA = qw(Exporter);
our @​EXPORT_OK = qw( );
our @​EXPORT = qw( );
our $VERSION = '0.01';

XSLoader​::load();

sub test2 {
  my ( $package_name ) = caller;

  print "My​::Caller​::test2() : $package_name\n";
}
1;

lib/My/Caller.xs​:


#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"

void test() {
  const PERL_CONTEXT *cx = caller_cx(0, NULL);
  if ( cx != NULL ) {
  char *pack_name = HvNAME((HV*)CopSTASH(cx->blk_oldcop));
  printf( "My​::Caller​::test() : %s\n", pack_name );
  }
  else {
  printf( "My​::Caller​::test() : NULL\n" );
  }
}

MODULE = My​::Caller PACKAGE = My​::Caller
PROTOTYPES​: DISABLE

void
test ()
  PREINIT​:
  I32* temp;
  PPCODE​:
  temp = PL_markstack_ptr++;
  test();
  if (PL_markstack_ptr != temp) {
  PL_markstack_ptr = temp;
  XSRETURN_EMPTY;
  }
  return;

Output from running p.pl​:


My​::Caller​::test() : NULL
My​::Caller​::test2() : main

Expected output​:


My​::Caller​::test() : main
My​::Caller​::test2() : main

Running Perl version 5.24.1 on Ubuntu 16.10.

The whole test case can be downloaded form here​:

https://github.com/hakonhagland/caller_cx_bug

See also​:
http​://stackoverflow.com/q/42531519/2173773

Best regards,
Håkon Hægland

@p5pRT
Copy link
Author

p5pRT commented Mar 6, 2017

From @iabyn

On Thu, Mar 02, 2017 at 12​:14​:27PM -0800, Håkon Hægland wrote​:

I am trying to figure out the package name of the caller from an XSUB.
It turns out that Perl C API function caller_cx(0,NULL) does not return
package name of caller, the same way as Perl function caller() does. For
example​:

From the docs for caller_cx()​:

  Note that XSUBs don't get a stack frame, so C<caller_cx(0, NULL)> will
  return information for the immediately-surrounding Perl code

Since you are calling the XS function 'test' directly from the main
body of the script, it will return NULL. Wrapping the call in a function
will give the result you expect, e.g.

  sub f { My​::Caller​::test() }
  package Bar;
  :​:f();

gives

  My​::Caller​::test() : Bar

--
Modern art​:
  "That's easy, I could have done that!"
  "Ah, but you didn't!"

@p5pRT
Copy link
Author

p5pRT commented Mar 6, 2017

The RT System itself - Status changed from 'new' to 'open'

@p5pRT
Copy link
Author

p5pRT commented Mar 6, 2017

From @hakonhagland

Thanks Dave Mitchell! Wrapping the XSUB call in a Perl subroutine works
perfectly.

2017-03-06 13​:01 GMT+01​:00 Dave Mitchell via RT <perlbug-followup@​perl.org>​:

On Thu, Mar 02, 2017 at 12​:14​:27PM -0800, Håkon Hægland wrote​:

I am trying to figure out the package name of the caller from an XSUB.
It turns out that Perl C API function caller_cx(0,NULL) does not return
package name of caller, the same way as Perl function caller() does. For
example​:

From the docs for caller_cx()​:

Note that XSUBs don't get a stack frame\, so C\<caller\_cx\(0\, NULL\)> will
return information for the immediately\-surrounding Perl code

Since you are calling the XS function 'test' directly from the main
body of the script, it will return NULL. Wrapping the call in a function
will give the result you expect, e.g.

sub f \{ My&#8203;::Caller&#8203;::test\(\) \}
package Bar;
:&#8203;:f\(\);

gives

My&#8203;::Caller&#8203;::test\(\) : Bar

--
Modern art​:
"That's easy, I could have done that!"
"Ah, but you didn't!"

@p5pRT
Copy link
Author

p5pRT commented Mar 6, 2017

From @KES777

I think perl today should provide some thing like current context (and such structure already exists in the CORE)
Also there are already many things publically visible​:
@​current_context = __PACKAGE__ __FILE__ __LINE__ __SUB__ @​ARGV/@​_, $^H, $%H

And when sub is called perl just​: push @​stack, \@​current_context;

Today we should group all those things together

( Does API exists already? http​://stackoverflow.com/questions/42629915/is-there-a-way-to-access-special-tokens-in-perl-from-xs )

@p5pRT p5pRT closed this as completed Mar 29, 2017
@p5pRT
Copy link
Author

p5pRT commented Mar 29, 2017

@iabyn - Status changed from 'open' to 'rejected'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant