diff options
author | Ben Gamari <bgamari.foss@gmail.com> | 2018-05-27 11:48:53 -0400 |
---|---|---|
committer | Ben Gamari <ben@smart-cactus.org> | 2018-05-30 10:02:10 -0400 |
commit | 34464fed463c7be07d4664e2f4b96eaf1acfc37b (patch) | |
tree | b6b4c19990c8e7d0100e144086fef1f956a7cb26 /rts/posix | |
parent | 49e423e9940a9122a4a417cfc7580b9984fb49eb (diff) | |
download | haskell-34464fed463c7be07d4664e2f4b96eaf1acfc37b.tar.gz |
rts: Don't madvise if mmap failed
On 32-bit Linux `outofmem` did not fail with the expected out-of-memory
error message, instead failing with,
outofmem: internal error: getMBlock: mmap: Invalid argument
This happened because, `my_mmap` would attempt to `madvise` even if the
`mmap` call failed. So while `mmap` returns `ENOMEM` we nevertheless try
to `madvise`, which clobbers `errno`, giving us the unexpected `EINVAL`
error. Consequently we don't detect this to be an out-of-memory error.
This should fix #15060.
Test Plan: `make test TEST=outofmem` on i386
Reviewers: simonmar, erikd
Reviewed By: simonmar
Subscribers: rwbarton, thomie, carter
GHC Trac Issues: #15060
Differential Revision: https://phabricator.haskell.org/D4704
Diffstat (limited to 'rts/posix')
-rw-r--r-- | rts/posix/OSMem.c | 14 |
1 files changed, 8 insertions, 6 deletions
diff --git a/rts/posix/OSMem.c b/rts/posix/OSMem.c index 9ecd53e9db..1df18abf6e 100644 --- a/rts/posix/OSMem.c +++ b/rts/posix/OSMem.c @@ -192,16 +192,18 @@ my_mmap (void *addr, W_ size, int operation) } } - if (operation & MEM_COMMIT) { - madvise(ret, size, MADV_WILLNEED); + if (ret != (void *)-1) { + if (operation & MEM_COMMIT) { + madvise(ret, size, MADV_WILLNEED); #if defined(MADV_DODUMP) - madvise(ret, size, MADV_DODUMP); + madvise(ret, size, MADV_DODUMP); #endif - } else { - madvise(ret, size, MADV_DONTNEED); + } else { + madvise(ret, size, MADV_DONTNEED); #if defined(MADV_DONTDUMP) - madvise(ret, size, MADV_DONTDUMP); + madvise(ret, size, MADV_DONTDUMP); #endif + } } #else |