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

unexpected behavior from cglobal pointers #2501

Open
emakman opened this issue Nov 19, 2018 · 1 comment

Comments

Projects
None yet
2 participants
@emakman
Copy link

commented Nov 19, 2018

I was playing around with the NCurses bindings and ran into an issue with a cglobal pointer.

The Problem

ncurses exports a variable pointer $stdscr, which is in turn accessed in the NCurses module by cglobal. (returning a class which is repr<CPointer>). When this in turn is plugged into native functions expecting the same pointer type (for example, the wrefresh function), it causes a segfault.

Expected Behavior

The standard ncurses refresh() function should behave exactly the same as wrefresh(stdscr) (in fact is a macro defined as wrefresh(stdscr)); the contents of the screen should be updated. In particular, I do not expect a segfault.

Actual Behavior

The program unexpectedly crashes.

Output (run with perl6 --ll-exception):
Segmentation fault (core dumped)

Steps to Reproduce

The issue with NCurses can be reproduced with the following code:

use NCurses;
initscr; endwin; # This guarantees sure stdscr has been set.
wrefresh(stdscr);

The corresponding C code compiles and executes correctly.

I seem to be able to avoid the problem if I avoid using cglobal pointers. The following executes as expected:

use NCurses;
use NativeCall;
initscr; endwin;
my \intptr_t = (nativesizeof(Pointer) == 8) ?? int64 !! int32;
my $stdscr := cglobal(library,'stdscr',intptr_t);
wrefresh(Pointer.new($stdscr));

Environment

  • Operating system:
    Arch Linux (4.18.16-arch1-1-ARCH)
  • Compiler version (perl6 -v):
    Rakudo version 2018.10-163-g50f0fce9b built on MoarVM version 2018.10-81-g7ba02259b
    implementing Perl 6.d.
@emakman

This comment has been minimized.

Copy link
Author

commented Nov 19, 2018

OK, after playing around, I have a better minimal example:

in libtest.c (compiled with gcc libtest.c -olibtest.so --shared -fPIC):

int a;
extern int *x = &a;
void SET() { a = 3; }
void GET(int *t) { return *t; }

in test.pl6:

use NativeCall;

my \LIB = 'PATH/TO/libtest.so';
my $x := cglobal(LIB,'x',Pointer);
my \interptr_t = (nativesizeof(Pointer) == 8) ?? int64 !! int32;
my $intx := cglobal(LIB,'x',intptr_t);

sub SET() is native{LIB} {*};
sub GET(Pointer) returns int32 is native{LIB} {*};
SET();
GET($x).say; # returns a random integer value;
GET(Pointer.new($intx)).say; # returns 3.

No segfault this time, but the cglobal pointer in $x still seems to be erroneous. I was hesitant o give this example originally because I don't know what I'm doing when it comes to C shared libraries, but I still would have expected GET($x) to return 3.

@emakman emakman closed this Nov 19, 2018

@emakman emakman reopened this Nov 19, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.