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

Embedded perl and putenv() don't always play nicely #339

Closed
p5pRT opened this issue Aug 4, 1999 · 8 comments
Closed

Embedded perl and putenv() don't always play nicely #339

p5pRT opened this issue Aug 4, 1999 · 8 comments

Comments

@p5pRT
Copy link

p5pRT commented Aug 4, 1999

Migrated from rt.perl.org#1170 (status was 'open')

Searchable as RT1170$

@p5pRT
Copy link
Author

p5pRT commented Aug 4, 1999

From Chris.Mihaly@disney.com

  Some recap on events. We were using perl 5.005_02 and have several
programs that have embeded perl in them. These programs would
sporadically coredump. After a lot of research, we debugged it back to
the fact that the C++ code was calling putenv after perl had run. When
perl ran, it had copied the _environ array into perl memory which then
caused putenv to die since it wanted to use the system memory routines.
Note that it is one application space but mutliple dynamic libraries.
Rasmus Tamstorf and myself submitted this problem quite a long time ago,
and Rasmus had submitted what we thought would fix this problem and
Gurusamy had put in a better patch to the perl code based on this
requested change.

  We then rebuilt perl 5.005_03 with the patch from Gurusamy. We first
tried to use the PERL_USE_SAFE_PUTENV method which worked in a limited
case. It would fail with a core dump if you ever did a 'delete
$ENV{foo}', since the delete thought it was perl memory and tried to
remove it as such, which it was not and it would core dump. There are
probably other such scenarios where perl intrinsics thought the $ENV{}
was in perl memory.

  We then went back to EMBEDMYMALLOC which caused perl to use system
memory routines for dealing with the _environ array. This worked, well
for a while. When 7.2.1 came out, this stopped working. Our program did
not core dump, but when our C++ program called putenv, these changes
were having no effect and subsequent subprocess would not see the new
environment variables. Our guess is that the _environ array cannot be
simply reassigned, that there is some other internal procesing that
keeps a copy of the pointer or the array. This is used by the new
putenv system call, but since perl realloced the array, in essense there
are now two environ arrays. This is highly speculative since we have
not had the ability to track this down yet, but the case is that it does
not work.

  I have no solution for this. The original way causes core dumps
because of mismatched memory usage, the EMBEDMYMALLOC causes putenv()
calls to be disregarded in embedded applications and the SAFE_PUTENV
causes many intrinsic perl operations to fail. We will continue to
investigate this problem, but the way that perl is handling the
environment is not compatable with embedded applications on SGIs.

  Chris

Gurusamy Sarathy wrote​:

On Tue, 08 Jun 1999 19​:44​:23 PDT, Chris Mihaly wrote​:

  We already are using EMBEDMYMALLOC\. The problem we were trying to

resolve was how the *environ object is being handled by our C++ program
and embedded perl.

Ahh, got it.

              The fix you included below was to make perl use the

system malloc when dealing with environ rather than copying it into a
Perl allocated space.

  We are a production environment\, so we are a bit weary of putting out

the latest dev version of Perl. So we though we would cheat, and take
the latest official release and try to put in your patch. However, I
think what is happening is that your patch is against a version that is
already much latter than 5.005_03. Is what we are doing hopless and we
should either wait until an offiical release is out or venture into the
latest development version?

It should be safe to change the places identified by the patch that use
New/Safefree/Renew (for allocating stuff pointed at by environ) to use
safemalloc/safefree/saferealloc instead. That should be a straightforward
change. I'd suggest ignoring the change in the name from safefoo() to
safesysfoo() for your purposes.

Sarathy
gsar@​activestate.com

--
Christopher Mihaly Email​: Chris.Mihaly@​disney.com
Walt Disney Feature Animation Phone​: (818) 560-9409
500 S. Buena Vista St. Fax​: (818) 560-8290
Burbank, CA 91521-4970

@p5pRT
Copy link
Author

p5pRT commented Aug 6, 1999

From [Unknown Contact. See original ticket]

Chris Mihaly writes​:

but the way that perl is handling the environment is not compatable
with embedded applications on SGIs.

(Chris, I'm a baby porter, so don't take anything I say as holy
gospel)

Given that Perl can't assume anything about how the process implements
its environment, it sounds like some kind of manual resync will be
required. That is, Perl maintains %ENV in Perl memory land, and every
change to %ENV corresponds to a putenv() call. However, if you're in
C world and do a putenv(), you would have a Perl_restore_environment()
call to ensure %ENV knows about the changed environment.

It appears that Perl can't use the process's environment space. If
Perl and C are to both be changing the environment, this (somewhat
kludgy) approach would seem to be the only way out.

Am I smoking crack?

Nat

@p5pRT
Copy link
Author

p5pRT commented Aug 6, 1999

From [Unknown Contact. See original ticket]

On Thu, 5 Aug 1999, Nathan Torkington wrote​:

Chris Mihaly writes​:

but the way that perl is handling the environment is not compatable
with embedded applications on SGIs.

(Chris, I'm a baby porter, so don't take anything I say as holy
gospel)

Given that Perl can't assume anything about how the process implements
its environment, it sounds like some kind of manual resync will be
required. That is, Perl maintains %ENV in Perl memory land, and every
change to %ENV corresponds to a putenv() call. However, if you're in
C world and do a putenv(), you would have a Perl_restore_environment()
call to ensure %ENV knows about the changed environment.

The approach you're describing here is in theory what PERL_USE_SAFE_PUTENV
does, but the implementation is incomplete in that 'delete $ENV{foo}' will
attempt to operate as if %ENV lives in perl memory. This causes a core
dump :-(

Am I smoking crack?

Nah, not quite, but whoever created the original semantics for putenv()
must have, 'cause otherwise we wouldn't have all these problems ;)

Rasmus


Rasmus.Tamstorf@​disney.com "A problem worthy of attack,
Walt Disney Feature Animation proves its worth by hitting back" Kumbel


@Michael1095
Copy link

Bruh its been 21 years, can someone fix this please lmao

@toddr
Copy link
Member

toddr commented Feb 15, 2020

@Michael1095 how do you suggest we fix it?

@toddr
Copy link
Member

toddr commented Feb 17, 2020

For starters, $0 scribbles on envp sometimes in order to lengthen it. https://github.com/Perl/perl5/blob/blead/perl.c#L1801

@toddr
Copy link
Member

toddr commented Feb 17, 2020

4efc5df seems to have added this comment after this ticket was opened:

/* only the parent thread can clobber the process environment */

@toddr
Copy link
Member

toddr commented Feb 17, 2020

The problem here (restated) appears to be C handing to Perl which manipulates %ENV and then wants to hand it back to C so more stuff can be done. It also appears to be re-using the memory provided to it by C to store the env vars. Perl doesn't understand that when it hands back, it needs to sync back %ENV into the C strings.

I SUSPECT that given the changes to SHEKs and COW over the years, this problem may be very different in a modern Perl these days.

Given the age of this ticket and lacking any practical examples to reproduce this issue or access to the referred to patch, I am closing this. If someone has more details or a recent example, please open a new ticket. Thanks!

@toddr toddr closed this as completed Feb 17, 2020
Blub added a commit to Blub/openssl-probe that referenced this issue Oct 9, 2023
As also stated in the stdlib documentation, setenv() is a bit of a
dangerous interface and can cause a lot of headaches. For instance,
perl before version 5.38 (at the time of writing, debian stable
(bookworm) uses version 5.36) manipulates the `environ` pointer
directly. When calling rust (or any other language) code from perl via
bindings, calling `setenv` easily leads to crashes[2].

In perl 5.38 this was fixed [1] and perl should itself also stick to using
`setenv`. This improves the situation a lot and leaves only the
threading issue we cannot solve here.

This commit allows the perl code to preset the environment variables
to avoid at least this instance of setenv causing crashes.

See-also: Perl/perl5#339
See-also: Perl/perl5#859
See-also: [1] Perl/perl5@916a038
See-also: [2] https://bugzilla.proxmox.com/show_bug.cgi?id=4979
Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
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

3 participants