# New Ticket Created by
# Please include the string: [perl #125243]
# in the subject line of all future correspondence about this issue.
# <URL: https://rt.perl.org/Ticket/Display.html?id=125243 >
A large category of C library functions will take a pointer to a struct
which will be populated by the function, a simple example is uname(3):
use v6;
use NativeCall;
class Utsname is repr('CStruct') {
has Str $.sysname;
has Str $.nodename;
has Str $.release;
has Str $.version;
has Str $.machine;
}
sub uname(Utsname $utsname is rw --> Int) is native { ... }
my $a = Utsname.new;
uname($a);
The above code will segfault (gdb bt:)
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7b55a51 in MVM_nativecall_refresh ()
from /home/jonathan/.rakudobrew/moar-nom/install/lib/libmoar.so
(gdb) bt
#0 0x00007ffff7b55a51 in MVM_nativecall_refresh ()
from /home/jonathan/.rakudobrew/moar-nom/install/lib/libmoar.so
#1 0x00007ffff7b5660e in MVM_nativecall_invoke ()
from /home/jonathan/.rakudobrew/moar-nom/install/lib/libmoar.so
#2 0x00007ffff7b33477 in MVM_interp_run ()
from /home/jonathan/.rakudobrew/moar-nom/install/lib/libmoar.so
#3 0x00007ffff7bd87ab in MVM_vm_run_file ()
from /home/jonathan/.rakudobrew/moar-nom/install/lib/libmoar.so
#4 0x000000000040101f in main ()
And valgrind:
================================================================================================
This is Rakudo Perl 6 running in valgrind, a tool for debugging
and profiling programs.
Running a program in valgrind usually takes *a lot* more time
than running it directly,
so please be patient.
This Rakudo version is 2015.5.14.g.800.f.703 built on MoarVM
version 2015.5,
running on fedora (21.Twenty.One) / linux
(1.SMP.Thu.May.7.22.0.21.UTC.2015)
------------------------------------------------------------------------------------------------
==16422== Memcheck, a memory error detector
==16422== Copyright (C) 2002-2013, and GNU GPL'd, by Julian
Seward et al.
==16422== Using Valgrind-3.10.1 and LibVEX; rerun with -h for
copyright info
==16422==
Command: /home/jonathan/.rakudobrew/moar-nom/install/bin/moar
--execname=/home/jonathan/.rakudobrew/bin/../moar-nom/install/bin/perl6-valgrind-m
--libpath=/home/jonathan/.rakudobrew/moar-nom/install/share/nqp/lib
--libpath=/home/jonathan/.rakudobrew/moar-nom/install/share/perl6/lib
--libpath=/home/jonathan/.rakudobrew/moar-nom/install/share/perl6/runtime
/home/jonathan/.rakudobrew/moar-nom/install/share/perl6/runtime/perl6.moarvm
tt.p6
==16422==
==16422== Syscall param uname(buf) points to unaddressable
byte(s)
==16422== at 0x39628C3C67: uname (syscall-template.S:81)
==16422== by 0x4E13F58: ???
(in /home/jonathan/.rakudobrew/moar-nom/install/lib/libmoar.so)
==16422== by 0xFFEFFF51F: ???
==16422== by 0x4E13E93: dc_callvm_call_x64
(in /home/jonathan/.rakudobrew/moar-nom/install/lib/libmoar.so)
==16422== by 0x39628C3C5F: ??? (in /usr/lib64/libc-2.20.so)
==16422== by 0xBE09B8F: ???
==16422== by 0x4D747DE: MVM_nativecall_invoke
(in /home/jonathan/.rakudobrew/moar-nom/install/lib/libmoar.so)
==16422== by 0x5788237: ???
==16422== by 0x9F1A11F: ???
==16422== by 0xA011E5F: ???
==16422== by 0x16: ???
==16422== by 0x7: ???
==16422== Address 0xaabd268 is 0 bytes after a block of size 40
alloc'd
==16422== at 0x4A08946: calloc
(in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==16422== by 0x4DA692B: initialize
(in /home/jonathan/.rakudobrew/moar-nom/install/lib/libmoar.so)
==16422== by 0x4D541A3: MVM_interp_run
(in /home/jonathan/.rakudobrew/moar-nom/install/lib/libmoar.so)
==16422== by 0x4DF67AA: MVM_vm_run_file
(in /home/jonathan/.rakudobrew/moar-nom/install/lib/libmoar.so)
==16422== by 0x40101E: main
(in /home/jonathan/.rakudobrew/moar-nom/install/bin/moar)
==16422==
==16422==
==16422== HEAP SUMMARY:
==16422== in use at exit: 54,868,899 bytes in 185,882 blocks
==16422== total heap usage: 346,369 allocs, 160,487 frees,
119,286,300 bytes allocated
==16422==
==16422== LEAK SUMMARY:
==16422== definitely lost: 52,412 bytes in 1,045 blocks
==16422== indirectly lost: 24,439 bytes in 923 blocks
==16422== possibly lost: 171,800 bytes in 3,071 blocks
==16422== still reachable: 54,620,248 bytes in 180,843 blocks
==16422== suppressed: 0 bytes in 0 blocks
==16422== Rerun with --leak-check=full to see details of leaked
memory
==16422==
==16422== For counts of detected and suppressed errors, rerun
with: -v
==16422== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0
from 0)
I think that it may actually be specific to something in the libc as a
much simpler case does actually work:
foo.c:
/*
gcc -c -fPIC -O3 -DNDEBUG -D_REENTRANT -D_FILE_OFFSET_BITS=64 -fPIC -o
foo.o foo.c
gcc -shared -fPIC -O3 -DNDEBUG
-Wl,-rpath,/home/jonathan/.rakudobrew/moar-nom/install/lib -lm -lpthread -lrt
-ldl -o foo.so foo.o
*/
struct Foo {
char *thing;
};
extern void do_foo(struct Foo *param) {
static char *bar = "Test";
param->thing = bar;
}
/*
void main() {
struct Foo baz;
do_foo(&baz);
printf("%s\n", baz.thing);
}
*/
foo.p6:
use v6;
use NativeCall;
class Foo is repr('CStruct') {
has Str $.thing is rw;
}
sub do_foo(Foo $foo is rw) is native('./foo.so') { ... }
my $a = Foo.new;
do_foo($a);
say $a.thing;
Does actually work as expected, so I'm quite will to accept that it's my
bug in the uname() code though I guess it shouldn't actually segfault
anyway.