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

sv_upgrade() loses 64-bit alignment, causing SIGBUS on sparc #9567

Closed
p5pRT opened this issue Nov 16, 2008 · 17 comments
Closed

sv_upgrade() loses 64-bit alignment, causing SIGBUS on sparc #9567

p5pRT opened this issue Nov 16, 2008 · 17 comments

Comments

@p5pRT
Copy link

p5pRT commented Nov 16, 2008

Migrated from rt.perl.org#60574 (status was 'resolved')

Searchable as RT60574$

@p5pRT
Copy link
Author

p5pRT commented Nov 16, 2008

From @ntyni

This is a bug report for perl from Niko Tyni <ntyni@​debian.org>
generated with the help of perlbug 1.39 running under perl 5.11.0.


As seen in <http​://bugs.debian.org/505415>, calling sv_chop() or otherwise
upgrading an SV can result in an unaligned 64-bit access on the sparc
architecture.

This was uncovered by the JSON-XS-2.23 test suite failing for us on
sparc with Perl 5.10.0. The failure is a SIGBUS that only occurs with
gcc optimization level -O2 or higher.

On 5.10.0, calling sv_chop() will upgrade the SV into an SVt_PVIV due
to the 'OOK hack'. The upgrade will allocate a new memory area for
sv->sv_any, possibly losing the 64-bit alignment in the process.

Calling the SvGROW() macro afterwards will cast sv->sv_any to an XPV
pointer, which should be 64-bit aligned according to __alignof__().
With -O2, gcc will compile the code using a doubleword load instruction
(ldd) that fails with a SIGBUS if the 64-bit alignment has been lost.

I'm attaching a test program that mimics what JSON-XS does when compiled
with -DUSE_CHOP. The test program compiled at -O2 dies with a SIGBUS
for me on the second doit() call.

This particular failure mode has been fixed in bleadperl with change
32836, which reimplements the 'OOK hack' in a different way so that the
SV isn't upgraded anymore. The failure is still present in maint-5.10,
as of change 34715.

However, it seems to me that this is a more general problem that should
be fixed by making sv_upgrade() somehow retain the alignment of the
existing SV.

The same test program, when compiled with -O2 but without -DUSE_CHOP
(making it explicitly call SvUPGRADE() instead), dies here on current
bleadperl (change 34714) with a SIGBUS on the second doit() call.

Note that using a debugging perl build (-DDEBUGGING) seems to defeat the crash.

Details for the bleadperl SIGBUS​:

Program received signal SIGBUS, Bus error.
[Switching to Thread 0xf7aca6b0 (LWP 32099)]
0x0001070c in doit () at crash.c​:15
15 SvGROW (sv, SvCUR (sv) + 1);
(gdb) bt
#0 0x0001070c in doit () at crash.c​:15
#1 0x00010774 in main (argc=<value optimized out>, argv=0xff995984, env=0xff995990) at crash.c​:25
(gdb) print *sv
$1 = {sv_any = 0x2569c, sv_refcnt = 1, sv_flags = 17413, sv_u = {svu_iv = 157328, svu_uv = 157328,
  svu_rv = 0x26690, svu_pv = 0x26690 "foo", svu_array = 0x26690, svu_hash = 0x26690, svu_gp = 0x26690}}

The preprocessor output for the above SvGROW() invocation is

(((XPV*) (sv)->sv_any)->xpv_len < (((XPV*) (sv)->sv_any)->xpv_cur + 1) ? Perl_sv_grow(my_perl, sv,((XPV*) (sv)->sv_any)->xpv_cur + 1) : ((sv)->sv_u.svu_pv));

The instruction that causes the bus error is a double-word load (ldd)
during the first comparison. The compiler (gcc -O2) is using the
double-word instruction to load both xpv_cur and xpv_len in one go.

0x00010708 <doit+56>​: ld [ %i1 ], %g1
0x0001070c <doit+60>​: ldd [ %g1 + 8 ], %g2
0x00010710 <doit+64>​: add %g2, 1, %i2
0x00010714 <doit+68>​: cmp %g3, %i2

Quoting Julien Cristau in the Debian bug​:

__alignof__(XPV) is 8, so gcc is allowed to assume that any XPV is
64-bit aligned, as far as I can tell. xpv_cur's offset is 8, so it
should also be 64-bit aligned.



Flags​:
  category=core
  severity=medium


Site configuration information for perl 5.11.0​:

Configured by niko at Sat Nov 15 18​:40​:57 UTC 2008.

Summary of my perl5 (revision 5 version 11 subversion 0) configuration​:
  Platform​:
  osname=linux, osvers=2.6.24-etchnhalf.1-sparc64-smp, archname=sparc-linux-gnu-thread-multi
  uname='linux raakel 2.6.24-etchnhalf.1-sparc64-smp #1 smp tue oct 14 04​:04​:33 utc 2008 sparc64 gnulinux '
  config_args='-Dusethreads -Duselargefiles -Dcccdlflags=-fPIC -Darchname=sparc-linux-gnu -Uafs -Ud_csh -Ud_ualarm -Uusesfio -Uusenm -DDEBUGGING=-g -Dprefix=/home/niko/bleadperl -Dusedevel -Doptimize=-O2 -Duseshrplib -Dlibperl=libperl.so.5.11.0 -des'
  hint=recommended, useposix=true, d_sigaction=define
  useithreads=define, usemultiplicity=define
  useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef
  use64bitint=undef, use64bitall=undef, uselongdouble=undef
  usemymalloc=n, bincompat5005=undef
  Compiler​:
  cc='cc', ccflags ='-D_REENTRANT -D_GNU_SOURCE -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
  optimize='-O2 -g',
  cppflags='-D_REENTRANT -D_GNU_SOURCE -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include'
  ccversion='', gccversion='4.3.2', gccosandvers=''
  intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=4321
  d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16
  ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
  alignbytes=8, prototype=define
  Linker and Libraries​:
  ld='cc', ldflags =' -fstack-protector -L/usr/local/lib'
  libpth=/usr/local/lib /lib /usr/lib /lib64 /usr/lib64
  libs=-lnsl -lgdbm -ldb -ldl -lm -lcrypt -lutil -lpthread -lc -lgdbm_compat
  perllibs=-lnsl -ldl -lm -lcrypt -lutil -lpthread -lc
  libc=/lib/libc-2.7.so, so=so, useshrplib=true, libperl=libperl.so.5.11.0
  gnulibc_version='2.7'
  Dynamic Linking​:
  dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E -Wl,-rpath,/home/niko/bleadperl/lib/5.11.0/sparc-linux-gnu-thread-multi/CORE'
  cccdlflags='-fPIC', lddlflags='-shared -O2 -g -L/usr/local/lib -fstack-protector'

Locally applied patches​:
  DEVEL


@​INC for perl 5.11.0​:
  /home/niko/bleadperl/lib/5.11.0/sparc-linux-gnu-thread-multi
  /home/niko/bleadperl/lib/5.11.0
  /home/niko/bleadperl/lib/site_perl/5.11.0/sparc-linux-gnu-thread-multi
  /home/niko/bleadperl/lib/site_perl/5.11.0
  .


Environment for perl 5.11.0​:
  HOME=/home/niko
  LANG (unset)
  LANGUAGE (unset)
  LD_LIBRARY_PATH (unset)
  LOGDIR (unset)
  PATH=/usr/local/bin​:/usr/bin​:/bin​:/usr/games
  PERL_BADLANG (unset)
  SHELL=/bin/sh

@p5pRT
Copy link
Author

p5pRT commented Nov 16, 2008

From @ntyni

#include <EXTERN.h>
#include <perl.h>

static PerlInterpreter *my_perl;
SV *sv;

void doit(void) {

	sv = newSVpv("foo", 3);
#ifdef USE_CHOP
	sv_chop(sv, SvPV_nolen(sv) + 1);
#else
	SvUPGRADE(sv, SVt_PVIV);
#endif
	SvGROW (sv, SvCUR (sv) + 1);
}

int main(int argc, char **argv, char **env)
{
	int i;
	my_perl = perl_alloc();

	for (i=0; i<10; i++) {
		printf("try %d\n", i);
		doit();
	}
}

@p5pRT
Copy link
Author

p5pRT commented Nov 16, 2008

From @nwc10

On Sun, Nov 16, 2008 at 04​:16​:14AM -0800, Niko Tyni wrote​:

As seen in <http​://bugs.debian.org/505415>, calling sv_chop() or otherwise
upgrading an SV can result in an unaligned 64-bit access on the sparc
architecture.

Calling the SvGROW() macro afterwards will cast sv->sv_any to an XPV
pointer, which should be 64-bit aligned according to __alignof__().
With -O2, gcc will compile the code using a doubleword load instruction
(ldd) that fails with a SIGBUS if the 64-bit alignment has been lost.

However, it seems to me that this is a more general problem that should
be fixed by making sv_upgrade() somehow retain the alignment of the
existing SV.

Yes, it's a more general problem.

The instruction that causes the bus error is a double-word load (ldd)
during the first comparison. The compiler (gcc -O2) is using the
double-word instruction to load both xpv_cur and xpv_len in one go.

Quoting Julien Cristau in the Debian bug​:

__alignof__(XPV) is 8, so gcc is allowed to assume that any XPV is
64-bit aligned, as far as I can tell. xpv_cur's offset is 8, so it
should also be 64-bit aligned.

What is __alignof__(XPVIV) and sizeof(XPVIV) on the same system?

cppflags='\-D\_REENTRANT \-D\_GNU\_SOURCE \-fno\-strict\-aliasing \-pipe \-fstack\-protector \-I/usr/local/include'

I see that -fno-strict-aliasing is on. That might prove relevant in my reply
to your reply.

Nicholas Clark

@p5pRT
Copy link
Author

p5pRT commented Nov 16, 2008

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

@p5pRT
Copy link
Author

p5pRT commented Nov 17, 2008

From @ntyni

On Sun, Nov 16, 2008 at 05​:15​:36PM +0000, Nicholas Clark wrote​:

On Sun, Nov 16, 2008 at 04​:16​:14AM -0800, Niko Tyni wrote​:

As seen in <http​://bugs.debian.org/505415>, calling sv_chop() or otherwise
upgrading an SV can result in an unaligned 64-bit access on the sparc
architecture.

What is __alignof__(XPVIV) and sizeof(XPVIV) on the same system?

8 and 24.

cppflags='\-D\_REENTRANT \-D\_GNU\_SOURCE \-fno\-strict\-aliasing \-pipe \-fstack\-protector \-I/usr/local/include'

I see that -fno-strict-aliasing is on. That might prove relevant in my reply
to your reply.

I didn't explicitly ask for it, so it would seem to be on by default.
--
Niko Tyni ntyni@​debian.org

@p5pRT
Copy link
Author

p5pRT commented Nov 17, 2008

From @nwc10

On Sun, Nov 16, 2008 at 08​:17​:17PM +0200, Niko Tyni wrote​:

On Sun, Nov 16, 2008 at 05​:15​:36PM +0000, Nicholas Clark wrote​:

On Sun, Nov 16, 2008 at 04​:16​:14AM -0800, Niko Tyni wrote​:

As seen in <http​://bugs.debian.org/505415>, calling sv_chop() or otherwise
upgrading an SV can result in an unaligned 64-bit access on the sparc
architecture.

What is __alignof__(XPVIV) and sizeof(XPVIV) on the same system?

8 and 24.

whereas __alignof__(xpv_allocated) and sizeof(xpv_allocated) are 8 and 4,
and __alignof__(xpviv_allocated) and sizeof(xpviv_allocated) are 12 and 4?

If so, that would explain a lot, and it's my fault.

I see that -fno-strict-aliasing is on. That might prove relevant in my reply
to your reply.

I didn't explicitly ask for it, so it would seem to be on by default.

It is Perl's default for gcc. I think it may not be relevant now.
I have an idea what is up, and some idea of how to fix it.

Nicholas Clark

@p5pRT
Copy link
Author

p5pRT commented Nov 18, 2008

From @ntyni

On Mon, Nov 17, 2008 at 03​:44​:18PM +0000, Nicholas Clark wrote​:

On Sun, Nov 16, 2008 at 08​:17​:17PM +0200, Niko Tyni wrote​:

On Sun, Nov 16, 2008 at 05​:15​:36PM +0000, Nicholas Clark wrote​:

On Sun, Nov 16, 2008 at 04​:16​:14AM -0800, Niko Tyni wrote​:

As seen in <http​://bugs.debian.org/505415>, calling sv_chop() or otherwise
upgrading an SV can result in an unaligned 64-bit access on the sparc
architecture.

What is __alignof__(XPVIV) and sizeof(XPVIV) on the same system?

8 and 24.

whereas __alignof__(xpv_allocated) and sizeof(xpv_allocated) are 8 and 4,
and __alignof__(xpviv_allocated) and sizeof(xpviv_allocated) are 12 and 4?

The other way around, otherwise right.

XPV​: alignof​: 8 sizeof​: 16
xpv_allocated​: alignof​: 4 sizeof​: 8
XPVIV​: alignof​: 8 sizeof​: 24
xpviv_allocated​: alignof​: 4 sizeof​: 12

If so, that would explain a lot, and it's my fault.

Looking forward to the explanation :)

Thanks for your work,
--
Niko Tyni ntyni@​debian.org

@p5pRT
Copy link
Author

p5pRT commented Dec 22, 2008

From au@hcsd.de

Hi,

I just ran into the same bug with Perl 5.8.8 compiled with Sun's
compiler (see below for details). Are there any workarounds or bugfixes
available? My (threaded) Perl application crashes due to this bug.

Regards,

Stephan

Summary of my perl5 (revision 5 version 8 subversion 8) configuration​:
  Platform​:
  osname=solaris, osvers=2.10, archname=sun4-solaris-thread-multi-64-ld
  uname='sunos fs2036 5.10 generic_127111-01 sun4u sparc
sunw,sparc-enterprise '
  config_args='-der'
  hint=previous, useposix=true, d_sigaction=define
  usethreads=define use5005threads=undef useithreads=define
usemultiplicity=define
  useperlio=define d_sfio=undef uselargefiles=define usesocks=undef
  use64bitint=define use64bitall=define uselongdouble=define
  usemymalloc=n, bincompat5005=undef
  Compiler​:
  cc='/opt/SUNWspro/bin/cc', ccflags ='-D_REENTRANT -m64
-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -DPERL_USE_SAFE_PUTENV
-DPERL_USE_SAFE_PUTENV -DPERL_USE_SAFE_PUTENV -DPERL_USE_SAFE_PUTENV
-DPERL_USE_SAFE_PUTENV -DPERL_USE_SAFE_PUTENV',
  optimize='-xO4',
  cppflags='-D_REENTRANT -m64 -D_REENTRANT -m64 -D_LARGEFILE_SOURCE
-D_FILE_OFFSET_BITS=64 -DPERL_USE_SAFE_PUTENV -DPERL_USE_SAFE_PUTENV
-D_REENTRANT -m64 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64
-DPERL_USE_SAFE_PUTENV -DPERL_USE_SAFE_PUTENV -DPERL_USE_SAFE_PUTENV
-DPERL_USE_SAFE_PUTENV'
  ccversion='Sun C 5.9 SunOS_sparc Patch 124867-01 2007/07/12',
gccversion='', gccosandvers=''
  intsize=4, longsize=8, ptrsize=8, doublesize=8, byteorder=87654321
  d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16
  ivtype='long', ivsize=8, nvtype='long double', nvsize=16,
Off_t='off_t', lseeksize=8
  alignbytes=16, prototype=define
  Linker and Libraries​:
  ld='/opt/SUNWspro/bin/cc', ldflags ='-m64
-L/opt/SUNWspro/prod/lib/v9 -L/lib/sparcv9 -L/usr/lib/sparcv9
-L/usr/ccs/lib/sparcv9 '
  libpth=/opt/SUNWspro/prod/lib/v9 /lib/sparcv9 /usr/lib/sparcv9
/usr/ccs/lib/sparcv9 /usr/lib /usr/ccs/lib
  libs=-lsocket -lnsl -ldl -lm -lpthread -lc -lsunmath
  perllibs=-lsocket -lnsl -ldl -lm -lpthread -lc -lsunmath
  libc=/usr/lib/sparcv9/libc.so, so=so, useshrplib=true,
libperl=libperl.so
  gnulibc_version=''
  Dynamic Linking​:
  dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags=' -R
/opt/mssperl5/lib/5.8.8/sun4-solaris-thread-multi-64-ld/CORE'
  cccdlflags='-KPIC', lddlflags='-G -m64 -L/opt/SUNWspro/prod/lib/v9
-L/lib/sparcv9 -L/usr/lib/sparcv9 -L/usr/ccs/lib/sparcv9'

Characteristics of this binary (from libperl)​:
  Compile-time options​: MULTIPLICITY PERL_IMPLICIT_CONTEXT
  PERL_MALLOC_WRAP PERL_USE_SAFE_PUTENV
  USE_64_BIT_ALL USE_64_BIT_INT USE_ITHREADS
  USE_LARGE_FILES USE_LONG_DOUBLE USE_PERLIO
  USE_REENTRANT_API
  Built under solaris
  Compiled at Apr 23 2008 15​:05​:33

@p5pRT
Copy link
Author

p5pRT commented Dec 22, 2008

From [Unknown Contact. See original ticket]

Hi,

I just ran into the same bug with Perl 5.8.8 compiled with Sun's
compiler (see below for details). Are there any workarounds or bugfixes
available? My (threaded) Perl application crashes due to this bug.

Regards,

Stephan

Summary of my perl5 (revision 5 version 8 subversion 8) configuration​:
  Platform​:
  osname=solaris, osvers=2.10, archname=sun4-solaris-thread-multi-64-ld
  uname='sunos fs2036 5.10 generic_127111-01 sun4u sparc
sunw,sparc-enterprise '
  config_args='-der'
  hint=previous, useposix=true, d_sigaction=define
  usethreads=define use5005threads=undef useithreads=define
usemultiplicity=define
  useperlio=define d_sfio=undef uselargefiles=define usesocks=undef
  use64bitint=define use64bitall=define uselongdouble=define
  usemymalloc=n, bincompat5005=undef
  Compiler​:
  cc='/opt/SUNWspro/bin/cc', ccflags ='-D_REENTRANT -m64
-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -DPERL_USE_SAFE_PUTENV
-DPERL_USE_SAFE_PUTENV -DPERL_USE_SAFE_PUTENV -DPERL_USE_SAFE_PUTENV
-DPERL_USE_SAFE_PUTENV -DPERL_USE_SAFE_PUTENV',
  optimize='-xO4',
  cppflags='-D_REENTRANT -m64 -D_REENTRANT -m64 -D_LARGEFILE_SOURCE
-D_FILE_OFFSET_BITS=64 -DPERL_USE_SAFE_PUTENV -DPERL_USE_SAFE_PUTENV
-D_REENTRANT -m64 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64
-DPERL_USE_SAFE_PUTENV -DPERL_USE_SAFE_PUTENV -DPERL_USE_SAFE_PUTENV
-DPERL_USE_SAFE_PUTENV'
  ccversion='Sun C 5.9 SunOS_sparc Patch 124867-01 2007/07/12',
gccversion='', gccosandvers=''
  intsize=4, longsize=8, ptrsize=8, doublesize=8, byteorder=87654321
  d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16
  ivtype='long', ivsize=8, nvtype='long double', nvsize=16,
Off_t='off_t', lseeksize=8
  alignbytes=16, prototype=define
  Linker and Libraries​:
  ld='/opt/SUNWspro/bin/cc', ldflags ='-m64
-L/opt/SUNWspro/prod/lib/v9 -L/lib/sparcv9 -L/usr/lib/sparcv9
-L/usr/ccs/lib/sparcv9 '
  libpth=/opt/SUNWspro/prod/lib/v9 /lib/sparcv9 /usr/lib/sparcv9
/usr/ccs/lib/sparcv9 /usr/lib /usr/ccs/lib
  libs=-lsocket -lnsl -ldl -lm -lpthread -lc -lsunmath
  perllibs=-lsocket -lnsl -ldl -lm -lpthread -lc -lsunmath
  libc=/usr/lib/sparcv9/libc.so, so=so, useshrplib=true,
libperl=libperl.so
  gnulibc_version=''
  Dynamic Linking​:
  dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags=' -R
/opt/mssperl5/lib/5.8.8/sun4-solaris-thread-multi-64-ld/CORE'
  cccdlflags='-KPIC', lddlflags='-G -m64 -L/opt/SUNWspro/prod/lib/v9
-L/lib/sparcv9 -L/usr/lib/sparcv9 -L/usr/ccs/lib/sparcv9'

Characteristics of this binary (from libperl)​:
  Compile-time options​: MULTIPLICITY PERL_IMPLICIT_CONTEXT
  PERL_MALLOC_WRAP PERL_USE_SAFE_PUTENV
  USE_64_BIT_ALL USE_64_BIT_INT USE_ITHREADS
  USE_LARGE_FILES USE_LONG_DOUBLE USE_PERLIO
  USE_REENTRANT_API
  Built under solaris
  Compiled at Apr 23 2008 15​:05​:33

@p5pRT
Copy link
Author

p5pRT commented Dec 22, 2008

From au@hcsd.de

Just to provide the core file details...

# dbx -f /opt/mssperl5/bin/perl core
For information about new features see `help changes'
To remove this message, put `dbxenv suppress_startup_message 7.6' in
your .dbxrc
Reading perl
core file header read successfully
Reading ld.so.1
Reading libperl.so
Reading libsocket.so.1
Reading libnsl.so.1
Reading libdl.so.1
Reading libm.so.2
Reading libpthread.so.1
Reading libc.so.1
Reading libc_psr.so.1
Reading de_DE.ISO8859-15.so.3
Reading en_US.ISO8859-1.so.3
Reading IO.so
Reading Socket.so
Reading POSIX.so
Reading Fcntl.so
Reading Storable.so
Reading Dumper.so
Reading default_store.so
Reading libnetsnmp.so.15.1.0
Reading libgen.so.1
Reading libelf.so.1
Reading libkstat.so.1
Reading libcrypto.so.0.9.8
Reading SNMP.so
Reading OID.so
Reading DBI.so
Reading Util.so
Reading Syck.so
Reading Tty.so
Reading threads.so
Reading shared.so
Reading HiRes.so
Reading librt.so.1
Reading libaio.so.1
Reading libmd.so.1
Reading Common.so
Reading libxml2.so.2.6.32
Reading libz.so.1
Reading LibXML.so
Reading Cwd.so
Reading B.so
t@​51 (l@​51) terminated by signal BUS (invalid address alignment)
0xffffffff7dab7ab8​: Perl_sv_upgrade+0x05b0​: ldx [%l7], %i0
(dbx) threads
 
  t@​1 a l@​1 ?() LWP suspended in __lwp_wait()
  t@​34 b l@​34 S_ithread_run() LWP suspended in _read()
  t@​35 b l@​35 S_ithread_run() LWP suspended in _read()
  t@​36 b l@​36 S_ithread_run() LWP suspended in _read()
  t@​37 b l@​37 S_ithread_run() LWP suspended in _read()
  t@​38 b l@​38 S_ithread_run() LWP suspended in _read()
  t@​39 b l@​39 S_ithread_run() LWP suspended in _read()
  t@​40 b l@​40 S_ithread_run() LWP suspended in _read()
  t@​41 b l@​41 S_ithread_run() LWP suspended in _read()
  t@​42 b l@​42 S_ithread_run() LWP suspended in _read()
  t@​43 b l@​43 S_ithread_run() LWP suspended in _read()
  t@​44 b l@​44 S_ithread_run() LWP suspended in _read()
  t@​45 b l@​45 S_ithread_run() LWP suspended in _read()
  t@​46 b l@​46 S_ithread_run() LWP suspended in _read()
  t@​47 b l@​47 S_ithread_run() LWP suspended in _read()
  t@​48 b l@​48 S_ithread_run() LWP suspended in _read()
  t@​49 b l@​49 S_ithread_run() LWP suspended in _read()
  t@​50 b l@​50 S_ithread_run() LWP suspended in _read()
o> t@​51 b l@​51 S_ithread_run() signal SIGBUS in Perl_sv_upgrade()
  t@​52 b l@​52 S_ithread_run() LWP suspended in _read()
  t@​53 b l@​53 S_ithread_run() LWP suspended in _read()
  t@​54 b l@​54 S_ithread_run() LWP suspended in _read()
  t@​55 b l@​55 S_ithread_run() LWP suspended in _memcpy()
  t@​56 b l@​56 S_ithread_run() LWP suspended in _read()
  t@​57 b l@​57 S_ithread_run() LWP suspended in _read()
  t@​58 b l@​58 S_ithread_run() LWP suspended in _read()
  t@​59 b l@​59 S_ithread_run() LWP suspended in _read()
  t@​60 b l@​60 S_ithread_run() LWP suspended in _read()
  t@​61 b l@​61 S_ithread_run() LWP suspended in _read()
  t@​62 b l@​62 S_ithread_run() LWP suspended in _read()
  t@​63 b l@​63 S_ithread_run() LWP suspended in _read()
  t@​64 b l@​64 S_ithread_run() LWP suspended in _read()
  t@​65 b l@​65 S_ithread_run() LWP suspended in _read()
(dbx) thread -info t@​51
  Thread t@​51 (0xffffffff7d10a200) at priority 0
  state​: bound to l@​51
  base function​: 0xffffffff7a2033d8​: S_ithread_run() stack​:
0xffffffff76efc000[2080768]
  flags​: BOUND|SUSPENDED
  masked signals​: (none)
  Currently active in Perl_sv_upgrade
(dbx) where
current thread​: t@​51
=>[1] Perl_sv_upgrade(0xffffffff7dab7480, 0x1228cc310, 0x1, 0x12d2133b0,
0x0, 0x0), at 0xffffffff7dab7ab8
  [2] Perl_sv_setsv_flags(0x12d2133b0, 0xeffffc00, 0x129c108a0, 0x2,
0x12d2133b0, 0x1228cc310), at 0xffffffff7dabce90
  [3] Perl_pp_sassign(0x12d2133b0, 0xb, 0x0, 0x2, 0x101078970,
0x129c108a0), at 0xffffffff7daab71c
  [4] Perl_runops_standard(0x12d2133b0, 0xffffffff7daab68c,
0xffffffff7daab270, 0x10121f2f0, 0xffffffff7d10a200, 0x101078970), at
0xffffffff7daab1c8
  [5] Perl_call_sv(0x12d2133b0, 0x125170740, 0x5, 0x1266c0b20, 0x1,
0x12d19e3e0), at 0xffffffff7da31aac
  [6] S_ithread_run(0x12d19e3e0, 0x1fc000, 0x0, 0x0, 0xffffffff7a2033d8,
0x1), at 0xffffffff7a203758

@p5pRT
Copy link
Author

p5pRT commented Dec 22, 2008

From [Unknown Contact. See original ticket]

Just to provide the core file details...

# dbx -f /opt/mssperl5/bin/perl core
For information about new features see `help changes'
To remove this message, put `dbxenv suppress_startup_message 7.6' in
your .dbxrc
Reading perl
core file header read successfully
Reading ld.so.1
Reading libperl.so
Reading libsocket.so.1
Reading libnsl.so.1
Reading libdl.so.1
Reading libm.so.2
Reading libpthread.so.1
Reading libc.so.1
Reading libc_psr.so.1
Reading de_DE.ISO8859-15.so.3
Reading en_US.ISO8859-1.so.3
Reading IO.so
Reading Socket.so
Reading POSIX.so
Reading Fcntl.so
Reading Storable.so
Reading Dumper.so
Reading default_store.so
Reading libnetsnmp.so.15.1.0
Reading libgen.so.1
Reading libelf.so.1
Reading libkstat.so.1
Reading libcrypto.so.0.9.8
Reading SNMP.so
Reading OID.so
Reading DBI.so
Reading Util.so
Reading Syck.so
Reading Tty.so
Reading threads.so
Reading shared.so
Reading HiRes.so
Reading librt.so.1
Reading libaio.so.1
Reading libmd.so.1
Reading Common.so
Reading libxml2.so.2.6.32
Reading libz.so.1
Reading LibXML.so
Reading Cwd.so
Reading B.so
t@​51 (l@​51) terminated by signal BUS (invalid address alignment)
0xffffffff7dab7ab8​: Perl_sv_upgrade+0x05b0​: ldx [%l7], %i0
(dbx) threads
 
  t@​1 a l@​1 ?() LWP suspended in __lwp_wait()
  t@​34 b l@​34 S_ithread_run() LWP suspended in _read()
  t@​35 b l@​35 S_ithread_run() LWP suspended in _read()
  t@​36 b l@​36 S_ithread_run() LWP suspended in _read()
  t@​37 b l@​37 S_ithread_run() LWP suspended in _read()
  t@​38 b l@​38 S_ithread_run() LWP suspended in _read()
  t@​39 b l@​39 S_ithread_run() LWP suspended in _read()
  t@​40 b l@​40 S_ithread_run() LWP suspended in _read()
  t@​41 b l@​41 S_ithread_run() LWP suspended in _read()
  t@​42 b l@​42 S_ithread_run() LWP suspended in _read()
  t@​43 b l@​43 S_ithread_run() LWP suspended in _read()
  t@​44 b l@​44 S_ithread_run() LWP suspended in _read()
  t@​45 b l@​45 S_ithread_run() LWP suspended in _read()
  t@​46 b l@​46 S_ithread_run() LWP suspended in _read()
  t@​47 b l@​47 S_ithread_run() LWP suspended in _read()
  t@​48 b l@​48 S_ithread_run() LWP suspended in _read()
  t@​49 b l@​49 S_ithread_run() LWP suspended in _read()
  t@​50 b l@​50 S_ithread_run() LWP suspended in _read()
o> t@​51 b l@​51 S_ithread_run() signal SIGBUS in Perl_sv_upgrade()
  t@​52 b l@​52 S_ithread_run() LWP suspended in _read()
  t@​53 b l@​53 S_ithread_run() LWP suspended in _read()
  t@​54 b l@​54 S_ithread_run() LWP suspended in _read()
  t@​55 b l@​55 S_ithread_run() LWP suspended in _memcpy()
  t@​56 b l@​56 S_ithread_run() LWP suspended in _read()
  t@​57 b l@​57 S_ithread_run() LWP suspended in _read()
  t@​58 b l@​58 S_ithread_run() LWP suspended in _read()
  t@​59 b l@​59 S_ithread_run() LWP suspended in _read()
  t@​60 b l@​60 S_ithread_run() LWP suspended in _read()
  t@​61 b l@​61 S_ithread_run() LWP suspended in _read()
  t@​62 b l@​62 S_ithread_run() LWP suspended in _read()
  t@​63 b l@​63 S_ithread_run() LWP suspended in _read()
  t@​64 b l@​64 S_ithread_run() LWP suspended in _read()
  t@​65 b l@​65 S_ithread_run() LWP suspended in _read()
(dbx) thread -info t@​51
  Thread t@​51 (0xffffffff7d10a200) at priority 0
  state​: bound to l@​51
  base function​: 0xffffffff7a2033d8​: S_ithread_run() stack​:
0xffffffff76efc000[2080768]
  flags​: BOUND|SUSPENDED
  masked signals​: (none)
  Currently active in Perl_sv_upgrade
(dbx) where
current thread​: t@​51
=>[1] Perl_sv_upgrade(0xffffffff7dab7480, 0x1228cc310, 0x1, 0x12d2133b0,
0x0, 0x0), at 0xffffffff7dab7ab8
  [2] Perl_sv_setsv_flags(0x12d2133b0, 0xeffffc00, 0x129c108a0, 0x2,
0x12d2133b0, 0x1228cc310), at 0xffffffff7dabce90
  [3] Perl_pp_sassign(0x12d2133b0, 0xb, 0x0, 0x2, 0x101078970,
0x129c108a0), at 0xffffffff7daab71c
  [4] Perl_runops_standard(0x12d2133b0, 0xffffffff7daab68c,
0xffffffff7daab270, 0x10121f2f0, 0xffffffff7d10a200, 0x101078970), at
0xffffffff7daab1c8
  [5] Perl_call_sv(0x12d2133b0, 0x125170740, 0x5, 0x1266c0b20, 0x1,
0x12d19e3e0), at 0xffffffff7da31aac
  [6] S_ithread_run(0x12d19e3e0, 0x1fc000, 0x0, 0x0, 0xffffffff7a2033d8,
0x1), at 0xffffffff7a203758

@p5pRT
Copy link
Author

p5pRT commented Jan 9, 2009

From au@hcsd.de

Quoting myself...

I just ran into the same bug with Perl 5.8.8 compiled with Sun's
compiler (see below for details). Are there any workarounds or bugfixes
available? My (threaded) Perl application crashes due to this bug.

I have fixed the SIGBUS by upgrading to Perl 5.8.9 and using a less
aggressive optimization with Sun's Workshop C compiler.

Regards,

Stephan

@p5pRT
Copy link
Author

p5pRT commented Jul 2, 2009

From @jimc

XPV and XPVIV are both special bodies, they use the ghost-fields trick,
which plays games that probably rub up against alignment issues.

I dont have a 64 bit machine, so I can only speculate,
but please consider changing s/HASARENA/NOARENA/ in the cases below,
and retesting ?

  /* 8 bytes on most ILP32 with IEEE doubles */
  { sizeof(xpv_allocated),
  copy_length(XPV, xpv_len)
  - relative_STRUCT_OFFSET(xpv_allocated, XPV, xpv_cur),
  + relative_STRUCT_OFFSET(xpv_allocated, XPV, xpv_cur),
  SVt_PV, FALSE, NONV, HASARENA, FIT_ARENA(0, sizeof(xpv_allocated)) },

  /* 12 */
  { sizeof(xpviv_allocated),
  copy_length(XPVIV, xiv_u)
  - relative_STRUCT_OFFSET(xpviv_allocated, XPVIV, xpv_cur),
  + relative_STRUCT_OFFSET(xpviv_allocated, XPVIV, xpv_cur),
  SVt_PVIV, FALSE, NONV, HASARENA, FIT_ARENA(0,
sizeof(xpviv_allocated)) },

@p5pRT
Copy link
Author

p5pRT commented Jul 17, 2009

From @nwc10

On Mon, Nov 17, 2008 at 08​:52​:28PM +0200, Niko Tyni wrote​:

On Mon, Nov 17, 2008 at 03​:44​:18PM +0000, Nicholas Clark wrote​:

On Sun, Nov 16, 2008 at 08​:17​:17PM +0200, Niko Tyni wrote​:

On Sun, Nov 16, 2008 at 05​:15​:36PM +0000, Nicholas Clark wrote​:

On Sun, Nov 16, 2008 at 04​:16​:14AM -0800, Niko Tyni wrote​:

As seen in <http​://bugs.debian.org/505415>, calling sv_chop() or otherwise
upgrading an SV can result in an unaligned 64-bit access on the sparc
architecture.

What is __alignof__(XPVIV) and sizeof(XPVIV) on the same system?

8 and 24.

whereas __alignof__(xpv_allocated) and sizeof(xpv_allocated) are 8 and 4,
and __alignof__(xpviv_allocated) and sizeof(xpviv_allocated) are 12 and 4?

The other way around, otherwise right.

XPV​: alignof​: 8 sizeof​: 16
xpv_allocated​: alignof​: 4 sizeof​: 8
XPVIV​: alignof​: 8 sizeof​: 24
xpviv_allocated​: alignof​: 4 sizeof​: 12

If so, that would explain a lot, and it's my fault.

Looking forward to the explanation :)

Thanks for your work,

Sorry for the delay. Does change 69ba284
fix it? It's currently in blead, but it should be suitable to merge to
maint-5.10. It replaces the *_allocated structs with a construction using
STRUCT_OFFSET().

I don't have access to sparc Debian, but I do have limited acces to sparc
Solaris 9 (with gcc). On that, running the appended script I see

bash-2.05$ ./perl -Ilib align.pl >align.c && gcc -Wall -o align align.c && ./align
XPV 16 8
xpv_allocated 8 4
sizeof(XPV) - STRUCT_OFFSET(XPV, xpv_cur) 8

XPVIV 24 8
xpviv_allocated 12 4
sizeof(XPVIV) - STRUCT_OFFSET(XPVIV, xpv_cur) 16

XPVAV 32 8
xpvav_allocated 20 4
sizeof(XPVAV) - STRUCT_OFFSET(XPVAV, xav_fill) 24

XPVHV 32 8
xpvhv_allocated 20 4
sizeof(XPVHV) - STRUCT_OFFSET(XPVHV, xhv_fill) 24

XPVCV 64 8
xpvcv_allocated 56 4
sizeof(XPVCV) - STRUCT_OFFSET(XPVCV, xpv_cur) 56

XPVFM 64 8
xpvfm_allocated 56 4
sizeof(XPVFM) - STRUCT_OFFSET(XPVFM, xpv_cur) 56

XPVIO 88 8
xpvio_allocated 76 4
sizeof(XPVIO) - STRUCT_OFFSET(XPVIO, xpv_cur) 80

regexp 96 8
struct regexp_allocated 88 4
sizeof(regexp) - STRUCT_OFFSET(regexp, xpv_cur) 88

bash-2.05$

  sizeof() ^ ^ __alignof__()

So I think the new way preserves the alignment constraint.

If I've got this right, I'll explain further if necessary. I'm not committing
to an explanation yet, as I don't know if I'm right.

Nicholas Clark

#!perl -w
use strict;

print <<'EOH';
#include "EXTERN.h"
#include "perl.h"

int main() {
EOH

my %first = (
  XPVAV => 'xav_fill',
  XPVHV => 'xhv_fill',
  );

my @​types = qw(XPV XPVIV XPVAV XPVHV XPVCV XPVFM);
push @​types, qw(XPVIO regexp) if $] >= 5.011;

foreach my $raw (@​types) {
  foreach my $struct (map {$_, "\L$_\E_allocated"} $raw) {
  $struct = "struct $struct" if $struct eq 'regexp_allocated';
  print qq{printf("%-48s\\t%d\t%d\\n", "$struct"};
  print ", $_($struct)" foreach qw(sizeof __alignof__);
  print ")\n;";
  }
  my $first = $first{$raw} || 'xpv_cur';
  my $new = "sizeof($raw) - STRUCT_OFFSET($raw, $first)";
  print qq{printf("%-48s\\t%d\\n\\n", "$new", $new);\n};
}

print <<'EOH';
  return 0;
}
EOH

__END__

@p5pRT
Copy link
Author

p5pRT commented Jul 23, 2009

From @ntyni

On Fri, Jul 17, 2009 at 08​:44​:40PM +0100, Nicholas Clark wrote​:

On Mon, Nov 17, 2008 at 08​:52​:28PM +0200, Niko Tyni wrote​:

On Mon, Nov 17, 2008 at 03​:44​:18PM +0000, Nicholas Clark wrote​:

On Sun, Nov 16, 2008 at 08​:17​:17PM +0200, Niko Tyni wrote​:

On Sun, Nov 16, 2008 at 05​:15​:36PM +0000, Nicholas Clark wrote​:

On Sun, Nov 16, 2008 at 04​:16​:14AM -0800, Niko Tyni wrote​:

As seen in <http​://bugs.debian.org/505415>, calling sv_chop() or otherwise
upgrading an SV can result in an unaligned 64-bit access on the sparc
architecture.

What is __alignof__(XPVIV) and sizeof(XPVIV) on the same system?

8 and 24.

whereas __alignof__(xpv_allocated) and sizeof(xpv_allocated) are 8 and 4,
and __alignof__(xpviv_allocated) and sizeof(xpviv_allocated) are 12 and 4?

Sorry for the delay. Does change 69ba284
fix it? It's currently in blead, but it should be suitable to merge to
maint-5.10. It replaces the *_allocated structs with a construction using
STRUCT_OFFSET().

Yes, I can confirm it fixes it all for me on both blead and maint-5.10,
including the original problem (failing JSON-XS test suite on maint-5.10).

I don't have access to sparc Debian, but I do have limited acces to sparc
Solaris 9 (with gcc). On that, running the appended script I see

This is the output on maint-5.10 here​:

XPV 16 8
xpv_allocated 8 4
sizeof(XPV) - STRUCT_OFFSET(XPV, xpv_cur) 8

XPVIV 24 8
xpviv_allocated 12 4
sizeof(XPVIV) - STRUCT_OFFSET(XPVIV, xpv_cur) 16

XPVAV 32 8
xpvav_allocated 20 4
sizeof(XPVAV) - STRUCT_OFFSET(XPVAV, xav_fill) 24

XPVHV 32 8
xpvhv_allocated 20 4
sizeof(XPVHV) - STRUCT_OFFSET(XPVHV, xhv_fill) 24

XPVCV 64 8
xpvcv_allocated 56 4
sizeof(XPVCV) - STRUCT_OFFSET(XPVCV, xpv_cur) 56

XPVFM 72 8
xpvfm_allocated 60 4
sizeof(XPVFM) - STRUCT_OFFSET(XPVFM, xpv_cur) 64

Many thanks for your work! Much appreciated.
--
Niko Tyni ntyni@​debian.org

@p5pRT
Copy link
Author

p5pRT commented Aug 26, 2009

From @nwc10

Resolved and released. I want to close the RT ticket now, but I still
owe you the explanation of what the code was doing, and why. I will get
round to that, but maybe not for a few weeks still.

Nicholas Clark

@p5pRT
Copy link
Author

p5pRT commented Aug 26, 2009

@nwc10 - Status changed from 'open' to 'resolved'

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

No branches or pull requests

1 participant