summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorÆvar Arnfjörð Bjarmason <avar@cpan.org>2012-02-11 17:17:31 +0000
committerÆvar Arnfjörð Bjarmason <avar@cpan.org>2012-02-12 15:46:38 +0000
commit8c442cc912aa3e4ce1898785f92c5a1e8fb0b4d8 (patch)
treec39f6b3c03c95f6c9d91ecbe393ee4381ec92cc8
parent8852e312c3c616ab731ccbe7da54fb04eb8c3d30 (diff)
downloadperl-avar/remove-linuxthreads-pid-caching.tar.gz
Further eliminate POSIX-emulation under LinuxThreadsavar/remove-linuxthreads-pid-caching
Under POSIX threads the getpid() and getppid() functions return the same values across multiple threads, i.e. threads don't have their own PID's. This is not the case under the obsolete LinuxThreads where each thread has a different PID, so getpid() and getppid() will return different values across threads. Ever since the first perl 5.0 we've returned POSIX-consistent semantics for $$, until v5.14.0-251-g0e21945 when the getpid() cache was removed. In 5.8.1 Rafael added further explicit POSIX emulation in perl-5.8.0-133-g4d76a34 [1] by explicitly caching getppid(), so that multiple threads would always return the same value. I don't think all this effort to emulate POSIX sematics is worth it. I think $$ and getppid() are OS-level functions that should always return the same as their C equivalents. I shouldn't have to use a module like Linux::Pid to get the OS version of the return values. This is pretty much a complete non-issue in practice these days, LinuxThreads was a Linux 2.4 thread implementation that nobody maintains anymore[2], all modern Linux distros use NPTL threads which don't suffer from this discrepancy. Debian GNU/kFreeBSD does use LinuxThreads in the 6.0 release, but they too will be moving away from it in future releases. This caching makes it unnecessarily tedious to fork an embedded Perl interpreter. When someone that constructs an embedded perl interpreter and forks their application, the fork(2) system call isn't going to run Perl_pp_fork(), and thus the return value of $$ and getppid() doesn't reflect the current process. See [3] for a bug in uWSGI related to this, and Perl::AfterFork for XS code that you need to run after forking a PerlInterpreter unbeknownst to perl. We've already been failing the tests in t/op/getpid.t on these Linux systems that nobody apparently uses, the Debian GNU/kFreeBSD users did notice and filed #96270, this patch fixes that failure by changing the tests to test for different behavior under LinuxThreads, I've tested that this works on my Debian GNU/kFreeBSD 6.0.4 box. If this change is found to be unacceptable (i.e. we want to continue to emulate POSIX thread semantics for the sake of LinuxThreads) we also need to revert v5.14.0-251-g0e21945, because currently we're only emulating POSIX semantics for getppid(), not getpid(). This commit includes a change to embedvar.h made by "make regen_headers". 1. http://www.nntp.perl.org/group/perl.perl5.porters/2002/08/msg64603.html 2. http://pauillac.inria.fr/~xleroy/linuxthreads/ 3. http://projects.unbit.it/uwsgi/ticket/85
-rw-r--r--embedvar.h1
-rw-r--r--hints/linux.sh8
-rw-r--r--intrpvar.h5
-rw-r--r--makedef.pl4
-rw-r--r--perl.c3
-rw-r--r--perl.h3
-rw-r--r--pod/perldelta.pod14
-rw-r--r--pod/perlfunc.pod10
-rw-r--r--pod/perlvar.pod22
-rw-r--r--pp_sys.c10
-rw-r--r--sv.c4
-rw-r--r--t/op/getpid.t15
-rw-r--r--util.c3
13 files changed, 49 insertions, 53 deletions
diff --git a/embedvar.h b/embedvar.h
index d56a53df41..bfb88e0b4f 100644
--- a/embedvar.h
+++ b/embedvar.h
@@ -265,7 +265,6 @@
#define PL_perlio (vTHX->Iperlio)
#define PL_phase (vTHX->Iphase)
#define PL_pidstatus (vTHX->Ipidstatus)
-#define PL_ppid (vTHX->Ippid)
#define PL_preambleav (vTHX->Ipreambleav)
#define PL_profiledata (vTHX->Iprofiledata)
#define PL_psig_name (vTHX->Ipsig_name)
diff --git a/hints/linux.sh b/hints/linux.sh
index d0ac9fa9ff..5713fafe81 100644
--- a/hints/linux.sh
+++ b/hints/linux.sh
@@ -365,15 +365,9 @@ fi
# This script UU/usethreads.cbu will get 'called-back' by Configure
# after it has prompted the user for whether to use threads.
cat > UU/usethreads.cbu <<'EOCBU'
-if getconf GNU_LIBPTHREAD_VERSION | grep NPTL >/dev/null 2>/dev/null
-then
- threadshavepids=""
-else
- threadshavepids="-DTHREADS_HAVE_PIDS"
-fi
case "$usethreads" in
$define|true|[yY]*)
- ccflags="-D_REENTRANT -D_GNU_SOURCE $threadshavepids $ccflags"
+ ccflags="-D_REENTRANT -D_GNU_SOURCE $ccflags"
if echo $libswanted | grep -v pthread >/dev/null
then
set `echo X "$libswanted "| sed -e 's/ c / pthread c /'`
diff --git a/intrpvar.h b/intrpvar.h
index fc4d64c7df..473c952e23 100644
--- a/intrpvar.h
+++ b/intrpvar.h
@@ -801,11 +801,6 @@ PERLVAR(I, memory_debug_header, struct perl_memory_debug_header)
PERLVARI(I, dumper_fd, int, -1)
#endif
-/* Stores the PPID */
-#ifdef THREADS_HAVE_PIDS
-PERLVARI(I, ppid, IV, 0)
-#endif
-
#ifdef PERL_MAD
PERLVARI(I, madskills, bool, FALSE) /* preserve all syntactic info */
/* (MAD = Misc Attribute Decoration) */
diff --git a/makedef.pl b/makedef.pl
index 002272bac7..a52241ff8c 100644
--- a/makedef.pl
+++ b/makedef.pl
@@ -422,10 +422,6 @@ unless ($define{'PERL_DEBUG_READONLY_OPS'}) {
);
}
-unless ($define{'THREADS_HAVE_PIDS'}) {
- ++$skip{PL_ppid};
-}
-
unless ($define{'PERL_NEED_APPCTX'}) {
++$skip{PL_appctx};
}
diff --git a/perl.c b/perl.c
index f754ac2112..c384e6d18e 100644
--- a/perl.c
+++ b/perl.c
@@ -4207,9 +4207,6 @@ S_init_postdump_symbols(pTHX_ register int argc, register char **argv, register
#endif /* !PERL_MICRO */
}
TAINT_NOT;
-#ifdef THREADS_HAVE_PIDS
- PL_ppid = (IV)getppid();
-#endif
/* touch @F array to prevent spurious warnings 20020415 MJD */
if (PL_minus_a) {
diff --git a/perl.h b/perl.h
index fe1eaecfb6..85387426ff 100644
--- a/perl.h
+++ b/perl.h
@@ -4693,9 +4693,6 @@ EXTCONST char PL_bincompat_options[] =
# ifdef PL_OP_SLAB_ALLOC
" PL_OP_SLAB_ALLOC"
# endif
-# ifdef THREADS_HAVE_PIDS
- " THREADS_HAVE_PIDS"
-# endif
# ifdef USE_64_BIT_ALL
" USE_64_BIT_ALL"
# endif
diff --git a/pod/perldelta.pod b/pod/perldelta.pod
index 07a684a49c..ffbed48da7 100644
--- a/pod/perldelta.pod
+++ b/pod/perldelta.pod
@@ -195,6 +195,20 @@ and the API will not be considered stable until v5.16.
See L<Unicode::UCD/prop_invmap()> for details on the new interface.
+=head2 C<$$> and C<getppid()> no longer emulate POSIX semantics under LinuxThreads
+
+The POSIX emulation of C<$$> and C<getppid()> under the obsolete
+LinuxThreads implementation has been removed (the C<$$> emulation was
+actually removed in v5.15.0). This only impacts users of Linux 2.4 and
+users of Debian GNU/kFreeBSD 6.0, not the vast majority of Linux
+installations that use NPTL threads.
+
+This means that C<getppid()> like C<$$> is now always guaranteed to
+return the OS's idea of the current state of the process, not perl's
+cached version of it.
+
+See the documentation for L<$$|perlvar/$$> for details.
+
=head1 Deprecations
XXX Any deprecated features, syntax, modules etc. should be listed here.
diff --git a/pod/perlfunc.pod b/pod/perlfunc.pod
index a5bffe4517..4a734d0531 100644
--- a/pod/perlfunc.pod
+++ b/pod/perlfunc.pod
@@ -2340,12 +2340,10 @@ X<getppid> X<parent> X<pid>
Returns the process id of the parent process.
-Note for Linux users: on Linux, the C functions C<getpid()> and
-C<getppid()> return different values from different threads. In order to
-be portable, this behavior is not reflected by the Perl-level function
-C<getppid()>, that returns a consistent value across threads. If you want
-to call the underlying C<getppid()>, you may use the CPAN module
-C<Linux::Pid>.
+Note for Linux users: Between v5.8.1 and v5.16.0 Perl would work
+around non-POSIX thread semantics the minority of Linux systems that
+used LinuxThreads, this emulation has since been removed. See the
+documentation for L<$$|perlvar/$$> for details.
Portability issues: L<perlport/getppid>.
diff --git a/pod/perlvar.pod b/pod/perlvar.pod
index 61ad1a9434..eb7468f180 100644
--- a/pod/perlvar.pod
+++ b/pod/perlvar.pod
@@ -191,11 +191,23 @@ this variable, doing so is generally discouraged, although it can be
invaluable for some testing purposes. It will be reset automatically
across C<fork()> calls.
-Note for Linux users: on Linux, the C functions C<getpid()> and
-C<getppid()> return different values from different threads. In order to
-be portable, this behavior is not reflected by C<$$>, whose value remains
-consistent across threads. If you want to call the underlying C<getpid()>,
-you may use the CPAN module C<Linux::Pid>.
+Note for Linux and Debian GNU/kFreeBSD users: Before Perl v5.16.0 perl
+would emulate POSIX semantics on Linux systems using LinuxThreads, a
+partial implementation of POSIX Threads that has since been superseded
+by the Native POSIX Thread Library (NPTL).
+
+LinuxThreads is now obsolete on Linux, and and caching C<getpid()>
+like this made embedding perl unnecessarily complex (since you'd have
+to manually update the value of $$), so now C<$$> and C<getppid()>
+will always return the same values as the underlying C library.
+
+Debian GNU/kFreeBSD systems also used LinuxThreads up until and
+including the 6.0 release, but after that moved to FreeBSD thread
+semantics, which are POSIX-like.
+
+To see if your system is affected by this discrepancy check if
+C<getconf GNU_LIBPTHREAD_VERSION | grep -q NPTL> returns a false
+value. NTPL threads preserve the POSIX semantics.
Mnemonic: same as shells.
diff --git a/pp_sys.c b/pp_sys.c
index d4f1b9f281..245e076d40 100644
--- a/pp_sys.c
+++ b/pp_sys.c
@@ -4043,9 +4043,6 @@ PP(pp_fork)
if (childpid < 0)
RETSETUNDEF;
if (!childpid) {
-#ifdef THREADS_HAVE_PIDS
- PL_ppid = (IV)getppid();
-#endif
#ifdef PERL_USES_PL_PIDSTATUS
hv_clear(PL_pidstatus); /* no kids, so don't wait for 'em */
#endif
@@ -4336,14 +4333,7 @@ PP(pp_getppid)
{
#ifdef HAS_GETPPID
dVAR; dSP; dTARGET;
-# ifdef THREADS_HAVE_PIDS
- if (PL_ppid != 1 && getppid() == 1)
- /* maybe the parent process has died. Refresh ppid cache */
- PL_ppid = 1;
- XPUSHi( PL_ppid );
-# else
XPUSHi( getppid() );
-# endif
RETURN;
#else
DIE(aTHX_ PL_no_func, "getppid");
diff --git a/sv.c b/sv.c
index 214a17d44b..04a101c1e3 100644
--- a/sv.c
+++ b/sv.c
@@ -13081,10 +13081,6 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
PL_globhook = proto_perl->Iglobhook;
-#ifdef THREADS_HAVE_PIDS
- PL_ppid = proto_perl->Ippid;
-#endif
-
/* swatch cache */
PL_last_swash_hv = NULL; /* reinits on demand */
PL_last_swash_klen = 0;
diff --git a/t/op/getpid.t b/t/op/getpid.t
index 7c1c04264b..7688240182 100644
--- a/t/op/getpid.t
+++ b/t/op/getpid.t
@@ -30,5 +30,16 @@ my $ppid2 : shared = 0;
new threads( sub { ($pid2, $ppid2) = ($$, getppid()); } ) -> join();
-is($pid, $pid2, 'pids');
-is($ppid, $ppid2, 'ppids');
+# If this breaks you're either running under LinuxThreads (and we
+# haven't detected it) or your system doesn't have POSIX thread
+# semantics.
+if ($^O =~ /^(?:gnukfreebsd|linux)$/ and
+ (my $linuxthreads = qx[getconf GNU_LIBPTHREAD_VERSION 2>&1]) =~ /linuxthreads/) {
+ chomp $linuxthreads;
+ diag "We're running under $^O with linuxthreads <$linuxthreads>";
+ isnt($pid, $pid2, "getpid() in a thread is different from the parent on this non-POSIX system");
+ isnt($ppid, $ppid2, "getppid() in a thread is different from the parent on this non-POSIX system");
+} else {
+ is($pid, $pid2, 'getpid() in a thread is the same as in the parent');
+ is($ppid, $ppid2, 'getppid() in a thread is the same as in the parent');
+}
diff --git a/util.c b/util.c
index fbe0f8da77..1ff591353c 100644
--- a/util.c
+++ b/util.c
@@ -2857,9 +2857,6 @@ Perl_my_popen(pTHX_ const char *cmd, const char *mode)
default, binary, low-level mode; see PerlIOBuf_open(). */
PerlLIO_setmode((*mode == 'r'), O_BINARY);
#endif
-#ifdef THREADS_HAVE_PIDS
- PL_ppid = (IV)getppid();
-#endif
PL_forkprocess = 0;
#ifdef PERL_USES_PL_PIDSTATUS
hv_clear(PL_pidstatus); /* we have no children */