Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 : * vim: sw=4 ts=4 et :
3 : */
4 : /* This Source Code Form is subject to the terms of the Mozilla Public
5 : * License, v. 2.0. If a copy of the MPL was not distributed with this
6 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 :
8 : #include "mozilla/mozalloc_abort.h"
9 : #include "mozilla/mozalloc_oom.h"
10 : #include "mozilla/Assertions.h"
11 :
12 : static mozalloc_oom_abort_handler gAbortHandler;
13 :
14 : #define OOM_MSG_LEADER "out of memory: 0x"
15 : #define OOM_MSG_DIGITS "0000000000000000" // large enough for 2^64
16 : #define OOM_MSG_TRAILER " bytes requested"
17 : #define OOM_MSG_FIRST_DIGIT_OFFSET sizeof(OOM_MSG_LEADER) - 1
18 : #define OOM_MSG_LAST_DIGIT_OFFSET sizeof(OOM_MSG_LEADER) + \
19 : sizeof(OOM_MSG_DIGITS) - 3
20 :
21 : static const char *hex = "0123456789ABCDEF";
22 :
23 : void
24 0 : mozalloc_handle_oom(size_t size)
25 : {
26 0 : char oomMsg[] = OOM_MSG_LEADER OOM_MSG_DIGITS OOM_MSG_TRAILER;
27 : size_t i;
28 :
29 : // NB: this is handle_oom() stage 1, which simply aborts on OOM.
30 : // we might proceed to a stage 2 in which an attempt is made to
31 : // reclaim memory
32 : // Warning: when stage 2 is done by, for example, notifying
33 : // "memory-pressure" synchronously, please audit all
34 : // nsExpirationTrackers and ensure that the actions they take
35 : // on memory-pressure notifications (via NotifyExpired) are safe.
36 : // Note that nsIDocument::SelectorCache::NotifyExpired is _known_
37 : // to not be safe: it will delete the selector it's caching,
38 : // which might be in use at the time under querySelector or
39 : // querySelectorAll.
40 :
41 0 : if (gAbortHandler)
42 0 : gAbortHandler(size);
43 :
44 : static_assert(OOM_MSG_FIRST_DIGIT_OFFSET > 0,
45 : "Loop below will never terminate (i can't go below 0)");
46 :
47 : // Insert size into the diagnostic message using only primitive operations
48 0 : for (i = OOM_MSG_LAST_DIGIT_OFFSET;
49 0 : size && i >= OOM_MSG_FIRST_DIGIT_OFFSET; i--) {
50 0 : oomMsg[i] = hex[size % 16];
51 0 : size /= 16;
52 : }
53 :
54 0 : mozalloc_abort(oomMsg);
55 : }
56 :
57 : void
58 0 : mozalloc_set_oom_abort_handler(mozalloc_oom_abort_handler handler)
59 : {
60 0 : gAbortHandler = handler;
61 0 : }
|