Issue metadata
Sign in to add a comment
|
chrome://memory-exhaust/ does not display correct sad tab on clang built binaries |
||||||||||||||||||||
Issue descriptionChrome Version: 57.0.2979.2 (Official Build) canary (64-bit) OS: Win 10 What steps will reproduce the problem? (1) go to chrome://memory-exhaust (2) (3) What is the expected result? Sad tab with "Google Chrome ran out of memory while trying to display this webpage." What happens instead? Sad tab with "Something went wrong while displaying this webpage". Please use labels and text to provide additional information. Works on 55.0.2883.87 (Official Build) m (64-bit) (Stable Channel) so this is a regression. For graphics-related bugs, please copy/paste the contents of the about:gpu page at the end of this report.
,
Jan 13 2017
,
Jan 13 2017
weird - I can't repro this with Chromium r443466 57.0.2980.0 (for bisect) so something more subtle must be wrong with my Chrome Canary. This message only appears on Windows.
,
Jan 14 2017
hmm doing chrome://memory-exhaust gives exit code = 1073741795 in chrome://histograms which is STATUS_ILLEGAL_INSTRUCTION. This makes little sense.
,
Jan 14 2017
now I suspect something to do with official builds and optimizations. I will try an official bisect.
,
Jan 14 2017
I was able to reproduce it on Linux, Chrome Beta (56).
,
Jan 14 2017
Repros for me on Canary here (and not on Stable)
,
Jan 14 2017
The custom "Google Chrome ran out of memory while trying to display this webpage." is only supported on Windows (unless someone else has implemented it on other platforms) so I'm not surprised that you get the standard "Something went wrong while displaying this webpage" on platforms other than Windows.
,
Jan 14 2017
Oh, but not on another Win Canary -- I suspect Compiler: clang now.
,
Jan 14 2017
ah yes, I am also compiler: clang - I hadn't noticed that before. clang can't call ::RaiseException...?
,
Jan 14 2017
yup, confirmed - on another machine running 57.0.2980.0 (Official Build) canary (64-bit) with compiler: MSVC (PGO) chrome://memory-exhaust works fine, so it's definitely something clang related.
,
Jan 14 2017
It calls malloc in a loop, maybe clang must thinks it's smart and knows something about undefined behaviour so it's allowed to just nuke early.
,
Jan 14 2017
This looks like the code that corresponds to
LOG(ERROR)
<< "Intentionally exhausting renderer memory because user navigated to "
<< url.spec();
ExhaustMemory();
So I don't think it thinks it needs to call ExhaustMemory().
00007ffe`3bc6f396 b902000000 mov ecx,2
00007ffe`3bc6f39b e8f0ec8efe call chrome_child!logging::ShouldCreateLogMessage (00007ffe`3a55e090)
00007ffe`3bc6f3a0 488d1529674901 lea rdx,[chrome_child!`string' (00007ffe`3d105ad0)]
00007ffe`3bc6f3a7 488d7c2440 lea rdi,[rsp+40h]
00007ffe`3bc6f3ac 41b81a020000 mov r8d,21Ah
00007ffe`3bc6f3b2 41b902000000 mov r9d,2
00007ffe`3bc6f3b8 4889f9 mov rcx,rdi
00007ffe`3bc6f3bb e810f18efe call chrome_child!logging::LogMessage::LogMessage (00007ffe`3a55e4d0)
00007ffe`3bc6f3c0 488d4c2448 lea rcx,[rsp+48h]
00007ffe`3bc6f3c5 488d152c814901 lea rdx,[chrome_child!`string' (00007ffe`3d1074f8)]
00007ffe`3bc6f3cc e8d73fcbfd call chrome_child!std::operator<<<std::char_traits<char> > (00007ffe`399233a8)
00007ffe`3bc6f3d1 4889c3 mov rbx,rax
00007ffe`3bc6f3d4 4c89e9 mov rcx,r13
00007ffe`3bc6f3d7 e8a63d9cfe call chrome_child!GURL::spec (00007ffe`3a633182)
00007ffe`3bc6f3dc 4889d9 mov rcx,rbx
00007ffe`3bc6f3df 4889c2 mov rdx,rax
00007ffe`3bc6f3e2 e8a9d7cffd call chrome_child!std::operator<<<char,std::char_traits<char>,std::allocator<char> > (00007ffe`3996cb90)
00007ffe`3bc6f3e7 4889f9 mov rcx,rdi
00007ffe`3bc6f3ea e831ed8efe call chrome_child!logging::LogMessage::~LogMessage (00007ffe`3a55e120)
00007ffe`3bc6f3ef 0f0b ud2
,
Jan 14 2017
It in fact declined to include ExhaustMemory() in the binary, citing concerns that "'twas a silly function": 0:000> x chrome_child!*ExhaustMemory* 0:000> x *!*ExhaustMemory* 0:000>
,
Jan 14 2017
it is indeed a silly function, so clang isn't wrong there.
,
Jan 14 2017
Running x='a';while(1)x+='a'; in devtools caused the correct oom display message, so just the debug url that's a problem.
,
Jan 16 2017
So, the fact that ExhaustMemory gets optimized away is expected. welcome to the club of "I was trying to fool my compiler around malloc and I lost".
If you start actually dereferencing volatile memory, the compiler should start showing some respect.
In other words I'd do:
void ExhaustMemory() {
volatile char* ptr;
for(;;) {
const size_t kSize = 0x10000000;
ptr = reinterpret_cast<volatile char*>(malloc(kSize));
if (!ptr) break;
ptr[0] = ptr[kSize - 1] + 1;
}
}
I am sure that there are a dozen carefully written sentences in the C++ specs, full of triple negatives, that make it so that you can't rely on this. But, in my limited experience, this trick has worked so far.
There are two IMHO disturbing things here:
1) The fact that the function was translated into a "ud2", which is essentially a crash.
I wouldn't have anything to say if the existing ExhaustMemory was optimized as a no-op.
I have something to say (see next point) if gets optimized as a while(true){}, but just learned to deal with that over time.
I am quite shocked by the fact that it gets translated into a __builtin_trap equivalent (ud2). ^__^
I am thrilled and frightened to understand why here.
I understand why this could have been the case for new/delete (There was a very good internal post I can't find right now, about new/delete and the fact that they are assumed to not fail even if you build with exceptions disabled), but this is a plain old malloc
2) A part of this confusion is generated by the fact that clang/LLVM seems to assume that malloc always returns non-null. While trying to repro this bug, I tried this on clang (both OSX and linux):
-----
void ExhaustMemory() {
volatile void* ptr = 0;
do { ptr = malloc(40); } while(ptr);
}
int main() {
ExhaustMemory();
return 1;
}
-----
$ clang++ test.cc -O1 -S -o -
.type _Z13ExhaustMemoryv,@function
_Z13ExhaustMemoryv: # @_Z13ExhaustMemoryv
.cfi_startproc
# BB#0: # %entry
.p2align 4, 0x90
.LBB0_1: # %do.body
# =>This Inner Loop Header: Depth=1
jmp .LBB0_1
Which essentially is a while(true){}.
And for the records, GCC is way more respectful on this.
Again, would have no objections if this was optimized as a no-op, or if this this was a "new". but this is assuming that malloc would always succeed.
There is a long discussion about this point in:
"[LLVMdev] optimization assumes malloc return is non-null" (https://groups.google.com/forum/#!topic/llvm-dev/lV30rcmF0ss)
and it makes me quite nervous. Because, if I read it correctly, it means that any code like:
x = malloc(...)
if (!x)
...
might cause, at best, an abundant laugh to clang/llvm.
We have that sort of stuff everywhere in the codebase, see https://cs.chromium.org/search/?q=if%5Cs*%5C(.*%5Cbmalloc%5Cb.*+f:%5C.c&sq=package:chromium&type=cs
The only good side is that once we convince the compiler to actually call malloc(), our own implementation (shim & co) guarantees the suicide in case of failure. So whether the false branch isn't hit doesn't make a difference.
But I wonder if, at this point, there is some other subtlety I'm not thinking about that could still bite us :-/
,
Jan 16 2017
,
Jan 16 2017
Would a base::debug::Alias(ptr) maybe persuade the compiler that the malloc can't be elided?
,
Jan 16 2017
Ah didn't thought to that but if it works that would IMHO be a great alternative, significantly more elegant than my horrendous hack.
,
Jan 17 2017
,
Jan 17 2017
I'll try a few of the suggested tricks and see what works.
,
Jan 17 2017
,
Feb 13 2017
The following revision refers to this bug: https://chromium.googlesource.com/chromium/src.git/+/3dcb0a73e6f194be62930e7e1924a0b6965f5637 commit 3dcb0a73e6f194be62930e7e1924a0b6965f5637 Author: wfh <wfh@chromium.org> Date: Mon Feb 13 20:53:00 2017 Fix ExhaustMemory on clang. Also, bolster the current tests to verify sad tab behavior. BUG= 681218 Review-Url: https://codereview.chromium.org/2648423006 Cr-Commit-Position: refs/heads/master@{#450078} [modify] https://crrev.com/3dcb0a73e6f194be62930e7e1924a0b6965f5637/chrome/browser/metrics/metrics_service_browsertest.cc [modify] https://crrev.com/3dcb0a73e6f194be62930e7e1924a0b6965f5637/content/renderer/render_frame_impl.cc
,
Apr 10 2017
I think Will fixed this. |
|||||||||||||||||||||
►
Sign in to add a comment |
|||||||||||||||||||||
Comment 1 by wfh@chromium.org
, Jan 13 2017