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

die($object) in thread reblesses $object into main and breaks stringification #12023

Closed
p5pRT opened this issue Mar 29, 2012 · 6 comments
Closed

die($object) in thread reblesses $object into main and breaks stringification #12023

p5pRT opened this issue Mar 29, 2012 · 6 comments

Comments

@p5pRT
Copy link

@p5pRT p5pRT commented Mar 29, 2012

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

Searchable as RT112104$

@p5pRT
Copy link
Author

@p5pRT p5pRT commented Mar 29, 2012

From lasse.makholm@gmail.com

This is a bug report for perl from lasse.makholm@​gmail.com,
generated with the help of perlbug 1.39 running under perl 5.15.9.


When passing an object to die() in a thread, the object gets
reblessed into main before the thread termination warning is
printed. This breaks exception stringification​:

$ perl -e 'use threads; $t = threads->create(sub { die bless {}, "Foo"
}); $t->join'
Thread 1 terminated abnormally​: main=HASH(0x1576a48) at -e line 1.
$

The exception is cloned correctly into the main thread though​:

$ perl -e 'use threads; $t = threads->create(sub { die bless {}, "Foo"
}); $t->join; die $t->error'
Thread 1 terminated abnormally​: main=HASH(0x10b7d00) at -e line 1.
Foo=HASH(0xfb7f90)
$

I haven't been able to find any mentioning of this issue anywhere
but snooping around the source seems to indicate that this
behaviour has been around since perl-5.8.0-9301-g955c272.

The culprit is in threads.xs​:

  /* If ERRSV is an object, remember the classname and then
  * rebless into 'main' so it will survive 'cloning'
  */
  if (sv_isobject(thread->err)) {
  thread->err_class = HvNAME(SvSTASH(SvRV(thread->err)));
  sv_bless(thread->err, gv_stashpv("main", 0));
  }

...but that was added for a reason it seems. I'm not sure what
the appropriate fix should be.



Flags​:
  category=core
  severity=low


Site configuration information for perl 5.15.9​:

Configured by lasse at Wed Mar 28 17​:57​:13 CEST 2012.

Summary of my perl5 (revision 5 version 15 subversion 9) configuration​:
  Commit id​: 63429d5
  Platform​:
  osname=linux, osvers=3.0.0-16-generic, archname=x86_64-linux
  uname='linux plystrofyf 3.0.0-16-generic #28-ubuntu smp fri jan 27
17​:44​:39 utc 2012 x86_64 x86_64 x86_64 gnulinux '
  config_args='-de -Dusedevel'
  hint=recommended, useposix=true, d_sigaction=define
  useithreads=undef, usemultiplicity=undef
  useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef
  use64bitint=define, use64bitall=define, uselongdouble=undef
  usemymalloc=n, bincompat5005=undef
  Compiler​:
  cc='cc', ccflags ='-fno-strict-aliasing -pipe -fstack-protector
-I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
  optimize='-O2',
  cppflags='-fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include'
  ccversion='', gccversion='4.6.1', gccosandvers=''
  intsize=4, longsize=8, ptrsize=8, doublesize=8, byteorder=12345678
  d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16
  ivtype='long', ivsize=8, 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/x86_64-linux-gnu /lib/../lib
/usr/lib/x86_64-linux-gnu /usr/lib/../lib /lib /usr/lib
  libs=-lnsl -ldl -lm -lcrypt -lutil -lc
  perllibs=-lnsl -ldl -lm -lcrypt -lutil -lc
  libc=, so=so, useshrplib=false, libperl=libperl.a
  gnulibc_version='2.13'
  Dynamic Linking​:
  dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E'
  cccdlflags='-fPIC', lddlflags='-shared -O2 -L/usr/local/lib
-fstack-protector'

Locally applied patches​:


@​INC for perl 5.15.9​:
  lib
  /usr/local/lib/perl5/site_perl/5.15.9/x86_64-linux
  /usr/local/lib/perl5/site_perl/5.15.9
  /usr/local/lib/perl5/5.15.9/x86_64-linux
  /usr/local/lib/perl5/5.15.9
  .


Environment for perl 5.15.9​:
  HOME=/home/lasse
  LANG=da_DK.UTF-8
  LANGUAGE=en_GB​:en
  LC_COLLATE=en_GB.UTF-8
  LC_CTYPE=en_GB.UTF-8
  LC_MESSAGES=en_GB.UTF-8
  LD_LIBRARY_PATH (unset)
  LOGDIR (unset)
  PATH=/usr/lib/lightdm/lightdm​:/usr/local/sbin​:/usr/local/bin​:/usr/sbin​:/usr/bin​:/sbin​:/bin​:/usr/games
  PERL_BADLANG (unset)
  SHELL=/bin/bash

@p5pRT
Copy link
Author

@p5pRT p5pRT commented Mar 29, 2012

From @cpansprout

On Thu Mar 29 02​:52​:26 2012, lasse.makholm@​gmail.com wrote​:

This is a bug report for perl from lasse.makholm@​gmail.com,
generated with the help of perlbug 1.39 running under perl 5.15.9.

-----------------------------------------------------------------

When passing an object to die() in a thread, the object gets
reblessed into main before the thread termination warning is
printed. This breaks exception stringification​:

$ perl -e 'use threads; $t = threads->create(sub { die bless {}, "Foo"
}); $t->join'
Thread 1 terminated abnormally​: main=HASH(0x1576a48) at -e line 1.
$

The exception is cloned correctly into the main thread though​:

$ perl -e 'use threads; $t = threads->create(sub { die bless {}, "Foo"
}); $t->join; die $t->error'
Thread 1 terminated abnormally​: main=HASH(0x10b7d00) at -e line 1.
Foo=HASH(0xfb7f90)
$

I haven't been able to find any mentioning of this issue anywhere
but snooping around the source seems to indicate that this
behaviour has been around since perl-5.8.0-9301-g955c272.

The culprit is in threads.xs​:

        /\* If ERRSV is an object\, remember the classname and then
         \* rebless into 'main' so it will survive 'cloning'
         \*/
        if \(sv\_isobject\(thread\->err\)\) \{
            thread\->err\_class = HvNAME\(SvSTASH\(SvRV\(thread\-

err)));
sv_bless(thread->err, gv_stashpv("main", 0));
}

...but that was added for a reason it seems. I'm not sure what
the appropriate fix should be.

This appears to be a 5.8.9 regression​:

$ perl5.8.8 -e 'use threads; $t = threads->create(sub { die bless {}, "Foo"
}); $t->join'
thread failed to start​: Foo=HASH(0x87242c) at -e line 2.
$ perl5.8.9 -e 'use threads; $t = threads->create(sub { die bless {}, "Foo"
}); $t->join'
Thread 1 terminated abnormally​: main=HASH(0x87fdac) at -e line 2.

--

Father Chrysostomos

@p5pRT
Copy link
Author

@p5pRT p5pRT commented Mar 29, 2012

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

@p5pRT
Copy link
Author

@p5pRT p5pRT commented Apr 1, 2012

From @nwc10

On Thu, Mar 29, 2012 at 04​:06​:00PM -0700, Father Chrysostomos via RT wrote​:

On Thu Mar 29 02​:52​:26 2012, lasse.makholm@​gmail.com wrote​:

This is a bug report for perl from lasse.makholm@​gmail.com,
generated with the help of perlbug 1.39 running under perl 5.15.9.

When passing an object to die() in a thread, the object gets
reblessed into main before the thread termination warning is
printed. This breaks exception stringification​:

I haven't been able to find any mentioning of this issue anywhere
but snooping around the source seems to indicate that this
behaviour has been around since perl-5.8.0-9301-g955c272.

The culprit is in threads.xs​:

        /\* If ERRSV is an object\, remember the classname and then
         \* rebless into 'main' so it will survive 'cloning'
         \*/
        if \(sv\_isobject\(thread\->err\)\) \{
            thread\->err\_class = HvNAME\(SvSTASH\(SvRV\(thread\-

err)));
sv_bless(thread->err, gv_stashpv("main", 0));
}

...but that was added for a reason it seems. I'm not sure what
the appropriate fix should be.

I don't know either, but the idea of reblessing as implemented in that code
doesn't look sane.

However, this may start to touch on a deeper fundamental unsolvable problem
of ithreads - you can't be 100% sure *how* to clone something back into the
parent thread, because the object in the child thread is blessed into a
class not present in the parent thread, and there's no 100% sure way to
"autoload" the implementation of a class.

This appears to be a 5.8.9 regression​:

$ perl5.8.8 -e 'use threads; $t = threads->create(sub { die bless {}, "Foo"
}); $t->join'
thread failed to start​: Foo=HASH(0x87242c) at -e line 2.
$ perl5.8.9 -e 'use threads; $t = threads->create(sub { die bless {}, "Foo"
}); $t->join'
Thread 1 terminated abnormally​: main=HASH(0x87fdac) at -e line 2.

Well, as implied by commit hash referenced in the bug report, it's a
regression as a side effect of threads 1.54, and 5.8.9 updated to include
that module. The XS code in question was added with this​:

commit 955c272
Author​: Jerry D. Hedden <jdhedden@​cpan.org>
Date​: Thu Dec 14 03​:17​:47 2006 -0800

  threads 1.54 - Adds ->error() method
  From​: "Jerry D. Hedden" <jdhedden@​yahoo.com>
  Message-ID​: <20061214191748.98286.qmail@​web30209.mail.mud.yahoo.com>
 
  p4raw-id​: //depot/perl@​29557

Nicholas Clark

@p5pRT
Copy link
Author

@p5pRT p5pRT commented Dec 14, 2017

From zefram@fysh.org

Lasse Makholm wrote​:

I haven't been able to find any mentioning of this issue anywhere

The "bugs and limitations" section of the threads.pm documentation has a
note that returning blessed objects doesn't work. As discussed on [perl
#96538], making it work would involve maintaining more of a link between
objects in different threads than we can handle. The reblessing is crap,
but so is the undef that you get by returning a blessed object as your
non-error result. To return blessed objects you'll have to arrange your
own serialisation.

This ticket should be closed.

-zefram

@p5pRT
Copy link
Author

@p5pRT p5pRT commented Dec 14, 2017

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

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