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

Calling waitpid() on Windows can result in "panic: memory wrap" #16529

Closed
p5pRT opened this issue Apr 23, 2018 · 5 comments
Closed

Calling waitpid() on Windows can result in "panic: memory wrap" #16529

p5pRT opened this issue Apr 23, 2018 · 5 comments

Comments

@p5pRT
Copy link

p5pRT commented Apr 23, 2018

Migrated from rt.perl.org#133145 (status was 'new')

Searchable as RT133145$

@p5pRT
Copy link
Author

p5pRT commented Apr 23, 2018

From eajspm@gmail.com

Created by eajspm@gmail.com

This is a bug report for perl from eajspm@​gmail.com,
generated with the help of perlbug 1.40 running under perl 5.26.1.

-----------------------------------------------------------------
Calling waitpid(-1, WNOHANG) in a Perl script on Windows can result in the
Perl interpreter aborting with the error​:

panic​: memory wrap at script.pl line xx

The bug appears to be in either win32_internal_wait() or win32_msgwait() in
the
source file win32\win32.c. win32_msgwait() calls
MsgWaitForMultipleObjects().
If that call returns WAIT_OBJECT_0 + count, this is a special case that
means a
new message is available in the thread's input queue.

When this happens, the result WAIT_OBJECT_0 + count is returned to
win32_internal_wait(), but that function does not know how to properly deal
with that return code. It makes the bad assumption that the return code is
the
index of a thread that has finished and probably indexes into an invalid
location in an array or otherwise ends up corrupting memory somewhere (I
didn't
track down the exact source of the panic).

I put in a local fix to make win32_internal_wait() return 0 when
win32_msgwait() returns WAIT_OBJECT_0 _+ count and it solved the problem in
my
test program. A better solution would probably be to have win32_msgwait()
call
MsgWaitForMultipleObjects() again in this case since it technically didn't
complete the job it was asked to do. However, this is the first I've ever
looked at the Perl source code so I'm just guessing here.

There are several other places that call win32_msgwait(). They should all
be
inspected to see if they need to handle this return code as well.

Below is a simple program that I used to reproduce the problem and verify my
simple fix. I can readily reproduce the problem on one particular Windows
machine, but I cannot reproduce it on several other Windows machines. I'm
not
sure what the differences are. Perhaps it's because the machine where I can
reproduce it is a large machine with 16 cores and it can achieve a higher
level
of parallelism with the fork() calls. Either way, the bug is obvious if you
look through the source code.

=================================================================
use strict;
use warnings;

use POSIX "​:sys_wait_h";

# This is a simple program that spawns new "processes" with fork() as fast
as
# possible. The child processes do nothing except exit immediately. Each
time
# we fork a new process, we call waitpid() to clean up any child processes
that
# have finished. That way we should never have more than a few processes
# outstanding.
for (my $i = 1; $i <= 30000; $i++)
{
  my $pid = fork();
  if (! defined($pid))
  {
  die "*** fork() error​: $!\n";
  }
  elsif ($pid)
  {
  # Parent.
  my $done = 0;
  while (! $done)
  {
  my $ret = waitpid(-1, &WNOHANG);
  if ($ret == 0) {
  # No processes ready to reap.
  $done = 1;
  } elsif ($ret == -1) {
  # Error case. Not sure what we can do except retry later.
  $done = 1;
  } else {
  # Success case. Reaped a child process. Go around again.
  }
  }
  }
  else
  {
  # Child.
  print "Hello from child $i\n";
  exit;
  }
}

Perl Info

Flags:
    category=core
    severity=medium

Site configuration information for perl 5.26.1:

Configured by strawberry-perl at Sat Sep 23 23:10:19 2017.

Summary of my perl5 (revision 5 version 26 subversion 1) configuration:

  Platform:
    osname=MSWin32
    osvers=6.3
    archname=MSWin32-x86-multi-thread-64int
    uname='Win32 strawberry-perl 5.26.1.1 #1 Sat Sep 23 23:07:28 2017 i386'
    config_args='undef'
    hint=recommended
    useposix=true
    d_sigaction=undef
    useithreads=define
    usemultiplicity=define
    use64bitint=define
    use64bitall=undef
    uselongdouble=undef
    usemymalloc=n
    default_inc_excludes_dot=define
    bincompat5005=undef
  Compiler:
    cc='gcc'
    ccflags =' -s -O2 -DWIN32 -D__USE_MINGW_ANSI_STDIO
-DPERL_TEXTMODE_SCRIPTS -DPERL_IMPLICIT_CONTEXT -DPERL_IMPLICIT_SYS
-DUSE_PERLIO -fwrapv -fno-strict-aliasing -mms-bitfields'
    optimize='-s -O2'
    cppflags='-DWIN32'
    ccversion=''
    gccversion='7.1.0'
    gccosandvers=''
    intsize=4
    longsize=4
    ptrsize=4
    doublesize=8
    byteorder=12345678
    doublekind=3
    d_longlong=define
    longlongsize=8
    d_longdbl=define
    longdblsize=12
    longdblkind=3
    ivtype='long long'
    ivsize=8
    nvtype='double'
    nvsize=8
    Off_t='long long'
    lseeksize=8
    alignbytes=8
    prototype=define
  Linker and Libraries:
    ld='g++.exe'
    ldflags ='-s -L"D:\Apps\SPerl32Portable\perl\lib\CORE"
-L"D:\Apps\SPerl32Portable\c\lib"'
    libpth=D:\Apps\SPerl32Portable\c\lib
D:\Apps\SPerl32Portable\c\i686-w64-mingw32\lib
D:\Apps\SPerl32Portable\c\lib\gcc\i686-w64-mingw32\7.1.0
    libs= -lmoldname -lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32
-ladvapi32 -lshell32 -lole32 -loleaut32 -lnetapi32 -luuid -lws2_32 -lmpr
-lwinmm -lversion -lodbc32 -lodbccp32 -lcomctl32
    perllibs= -lmoldname -lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32
-ladvapi32 -lshell32 -lole32 -loleaut32 -lnetapi32 -luuid -lws2_32 -lmpr
-lwinmm -lversion -lodbc32 -lodbccp32 -lcomctl32
    libc=
    so=dll
    useshrplib=true
    libperl=libperl526.a
    gnulibc_version=''
  Dynamic Linking:
    dlsrc=dl_win32.xs
    dlext=xs.dll
    d_dlsymun=undef
    ccdlflags=' '
    cccdlflags=' '
    lddlflags='-mdll -s -L"D:\Apps\SPerl32Portable\perl\lib\CORE"
-L"D:\Apps\SPerl32Portable\c\lib"'



@INC for perl 5.26.1:
    d:/Apps/SPerl32Portable/perl/site/lib
    d:/Apps/SPerl32Portable/perl/vendor/lib
    d:/Apps/SPerl32Portable/perl/lib


Environment for perl 5.26.1:
    HOME (unset)
    LANG (unset)
    LANGUAGE (unset)
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)

PATH=d:\Apps\SPerl32Portable\c\i686-w64-mingw32\bin;d:\Apps\SPerl32Portable\c\bin;d:\Apps\SPerl32Portable\perl\site\bin;d:\Apps\SPerl32Portable\perl\bin;d:\rt\Apps\7-ZipPortable\App\7-Zip64;d:\rt\Apps\curl-7.57.0\bin;d:\rt\Apps\wget-1.19.1;C:\ProgramData\Oracle\Java\javapath;C:\Program
Files (x86)\NVIDIA
Corporation\PhysX\Common;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Users\Erik\AppData\Local\Microsoft\WindowsApps
    PERL_BADLANG (unset)
    SHELL (unset)

xenu added a commit to xenu/perl5 that referenced this issue Nov 10, 2019
waitpid(-1, WNOHANG) would panic or segfault if called when the
thread's message queue is not empty.

Thanks to Erik Jezierski for the report and diagnosis.

[gh Perl#16529]
khwilliamson pushed a commit that referenced this issue Nov 10, 2019
waitpid(-1, WNOHANG) would panic or segfault if called when the
thread's message queue is not empty.

Thanks to Erik Jezierski for the report and diagnosis.

[gh #16529]
@xenu
Copy link
Member

xenu commented Jan 17, 2020

Fixed in 08e55ec.

@xenu xenu closed this as completed Jan 17, 2020
steve-m-hay pushed a commit that referenced this issue Feb 12, 2020
waitpid(-1, WNOHANG) would panic or segfault if called when the
thread's message queue is not empty.

Thanks to Erik Jezierski for the report and diagnosis.

[gh #16529]

(cherry picked from commit 08e55ec)
@khwilliamson
Copy link
Contributor

Reopening to get in 5.32.1

@khwilliamson khwilliamson reopened this Aug 19, 2020
@khwilliamson khwilliamson added this to the 5.32.1 milestone Aug 19, 2020
@khwilliamson
Copy link
Contributor

This fix caused another bug fixed in 81295a4, and that should go into 5.30.1

khwilliamson added a commit that referenced this issue Aug 19, 2020
steve-m-hay pushed a commit that referenced this issue Jan 8, 2021
(cherry picked from commit df667af)
@xenu xenu removed the affects-5.26 label Nov 19, 2021
@tonycoz
Copy link
Contributor

tonycoz commented Dec 6, 2023

Fixed in all supported releases.

@tonycoz tonycoz closed this as completed Dec 6, 2023
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

4 participants