develooper Front page | perl.perl5.porters | Postings from February 2012

[PATCH] Further eliminate POSIX-emulation under LinuxThreads

Thread Previous | Thread Next
From:
Ævar Arnfjörð Bjarmason
Date:
February 11, 2012 11:57
Subject:
[PATCH] Further eliminate POSIX-emulation under LinuxThreads
Message ID:
1328990263-6640-1-git-send-email-avar@cpan.org
[This is a patch I've just committed to
avar/remove-linuxthreads-pid-caching) I'll be pushing it to blead
unless there are any sound objections to it]

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 also 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.

Furthermore 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.

We've already been failing the tests in t/op/getpid.t on these systems
that nobody apparently uses, just leave those tests in place as-is so
they'll start failing if perl ever runs on a system without POSIX
thread semantics.

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
---
 embedvar.h        |    1 -
 hints/linux.sh    |    8 +-------
 intrpvar.h        |    5 -----
 makedef.pl        |    4 ----
 perl.c            |    3 ---
 perl.h            |    3 ---
 pod/perldelta.pod |    8 ++++++++
 pod/perlfunc.pod  |   10 ++++------
 pod/perlvar.pod   |   18 +++++++++++++-----
 pp_sys.c          |   10 ----------
 sv.c              |    4 ----
 t/op/getpid.t     |    6 ++++--
 util.c            |    3 ---
 13 files changed, 30 insertions(+), 53 deletions(-)

diff --git a/embedvar.h b/embedvar.h
index 0321963..4d47666 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 d0ac9fa..5713faf 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 43e4e05..d72eb41 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 002272b..a52241f 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 f754ac2..c384e6d 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 fe1eaec..8538742 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 56825e6..4a6ec58 100644
--- a/pod/perldelta.pod
+++ b/pod/perldelta.pod
@@ -182,6 +182,14 @@ 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
+not the vast majority of Linux installations that use NPTL
+threads. 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 a5bffe4..4a734d0 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 61ad1a9..9c41dc8 100644
--- a/pod/perlvar.pod
+++ b/pod/perlvar.pod
@@ -191,11 +191,19 @@ 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 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, 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.
+
+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 d4f1b9f..245e076 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 068be55..94829de 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 7c1c042..67a0f90 100644
--- a/t/op/getpid.t
+++ b/t/op/getpid.t
@@ -30,5 +30,7 @@ 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 or your
+# system doesn't have POSIX thread semantics.
+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 fbe0f8d..1ff5913 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 */
-- 
1.7.8.3


Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About