-
Notifications
You must be signed in to change notification settings - Fork 578
Recursive call to mortal_getenv() causes deadlock #18341
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
Milestone
Comments
khwilliamson
added a commit
that referenced
this issue
Nov 26, 2020
This fixes GH #18341 getenv() call allocates memory to squirrel safely away the result of that getenv() call. It does this while in a critical section so as to make sure another thread can't interrupt it and destroy it. The problem when using PERL_MEM_LOG is that the allocation of that memory causes a recursive call to getenv() to see how to log that allocation. And it deadlocks trying to enter the critical section. There are various solutions. One is to use or emulate a general semaphore instead of a binary one. This is effectively what PL_lc_numeric_mutex_depth does for another mutex, and the code for that could be used as a template. But given that this is an extreme edge case which requires Perl to be specially compiled to enable this feature which is used only for debugging, I thought it would be sufficient to just make a special case to not try to lock during that recursive call.
khwilliamson
added a commit
that referenced
this issue
Nov 26, 2020
This fixes GH #18341 The Perl wrapper for getenv() was changed in 5.32 to allocate memory to squirrel safely away the result of the wrapped getenv() call. It does this while in a critical section so as to make sure another thread can't interrupt it and destroy it. Unfortunately, when Perl is compiled for debugging memory problems and has PERL_MEM_LOG enabled, that allocation causes a recursive call to getenv() for the purpose of checking an environment variable to see how to log that allocation. And hence it deadlocks trying to enter the critical section. There are various solutions. One is to use or emulate a general semaphore instead of a binary one. This is effectively what PL_lc_numeric_mutex_depth does for another mutex, and the code for that could be used as a template. But given that this is an extreme edge case which requires Perl to be specially compiled to enable this feature which is used only for debugging, a much simpler, if less safe if it were to ever be used in production, solution should suffice. Tony Cook suggested just avoiding the wrapper for this particular purpose.
khwilliamson
added a commit
that referenced
this issue
Nov 27, 2020
This fixes GH #18341 The Perl wrapper for getenv() was changed in 5.32 to allocate memory to squirrel safely away the result of the wrapped getenv() call. It does this while in a critical section so as to make sure another thread can't interrupt it and destroy it. Unfortunately, when Perl is compiled for debugging memory problems and has PERL_MEM_LOG enabled, that allocation causes a recursive call to getenv() for the purpose of checking an environment variable to see how to log that allocation. And hence it deadlocks trying to enter the critical section. There are various solutions. One is to use or emulate a general semaphore instead of a binary one. This is effectively what PL_lc_numeric_mutex_depth does for another mutex, and the code for that could be used as a template. But given that this is an extreme edge case which requires Perl to be specially compiled to enable this feature which is used only for debugging, a much simpler, if less safe if it were to ever be used in production, solution should suffice. Tony Cook suggested just avoiding the wrapper for this particular purpose.
This was fixed by 0cc28fe |
khwilliamson
added a commit
that referenced
this issue
Dec 12, 2020
This fixes GH #18341 There are problems with getenv() on threaded perls wchich can lead to incorrect results when compiled with PERL_MEM_LOG. Commit 0b83dfe fixed this for some platforms, but as Tony Cook, pointed out there may be standards-compliant platforms that that didn't fix. The detailed comments outline the issues and (complicated) full solution.
khwilliamson
added a commit
that referenced
this issue
Dec 17, 2020
This fixes GH #18341 There are problems with getenv() on threaded perls wchich can lead to incorrect results when compiled with PERL_MEM_LOG. Commit 0b83dfe fixed this for some platforms, but as Tony Cook, pointed out there may be standards-compliant platforms that that didn't fix. The detailed comments outline the issues and (complicated) full solution.
khwilliamson
added a commit
that referenced
this issue
Dec 17, 2020
This fixes GH #18341 There are problems with getenv() on threaded perls wchich can lead to incorrect results when compiled with PERL_MEM_LOG. Commit 0b83dfe fixed this for some platforms, but as Tony Cook, pointed out there may be standards-compliant platforms that that didn't fix. The detailed comments outline the issues and (complicated) full solution.
khwilliamson
added a commit
that referenced
this issue
Dec 20, 2020
This fixes GH #18341 There are problems with getenv() on threaded perls wchich can lead to incorrect results when compiled with PERL_MEM_LOG. Commit 0b83dfe fixed this for some platforms, but as Tony Cook, pointed out there may be standards-compliant platforms that that didn't fix. The detailed comments outline the issues and (complicated) full solution.
steve-m-hay
pushed a commit
that referenced
this issue
Jan 9, 2021
This fixes GH #18341 The Perl wrapper for getenv() was changed in 5.32 to allocate memory to squirrel safely away the result of the wrapped getenv() call. It does this while in a critical section so as to make sure another thread can't interrupt it and destroy it. Unfortunately, when Perl is compiled for debugging memory problems and has PERL_MEM_LOG enabled, that allocation causes a recursive call to getenv() for the purpose of checking an environment variable to see how to log that allocation. And hence it deadlocks trying to enter the critical section. There are various solutions. One is to use or emulate a general semaphore instead of a binary one. This is effectively what PL_lc_numeric_mutex_depth does for another mutex, and the code for that could be used as a template. But given that this is an extreme edge case which requires Perl to be specially compiled to enable this feature which is used only for debugging, a much simpler, if less safe if it were to ever be used in production, solution should suffice. Tony Cook suggested just avoiding the wrapper for this particular purpose. (cherry picked from commit 0cc28fe)
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I've just built blead with a configuration that I've been building quite regularly back in the days:
I'm pretty certain not all of this is needed for to reproduce the issue, but at least some of the
MEM_LOG
stuff is from a quick glance at the stack trace below.The first time
miniperl
gets run during the build, it hangs immediately. Here's a stack trace:I did a quick blame and reverted 24f3e84 and that fixed the deadlock. I didn't take a closer look yet, hopefully @khwilliamson has an idea :)
The text was updated successfully, but these errors were encountered: