oom.cc 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. // Copyright 2021 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "base/allocator/partition_allocator/oom.h"
  5. #include "base/allocator/partition_allocator/oom_callback.h"
  6. #include "base/allocator/partition_allocator/partition_alloc_base/compiler_specific.h"
  7. #include "base/allocator/partition_allocator/partition_alloc_base/debug/alias.h"
  8. #include "base/allocator/partition_allocator/partition_alloc_base/immediate_crash.h"
  9. #include "build/build_config.h"
  10. #if BUILDFLAG(IS_WIN)
  11. #include <windows.h>
  12. #include <stdlib.h>
  13. #include <array>
  14. #endif // BUILDFLAG(IS_WIN)
  15. namespace partition_alloc {
  16. size_t g_oom_size = 0U;
  17. namespace internal {
  18. // Crash server classifies base::internal::OnNoMemoryInternal as OOM.
  19. // TODO(crbug.com/1151236): Update to
  20. // partition_alloc::internal::base::internal::OnNoMemoryInternal
  21. PA_NOINLINE void OnNoMemoryInternal(size_t size) {
  22. g_oom_size = size;
  23. #if BUILDFLAG(IS_WIN)
  24. // Kill the process. This is important for security since most of code
  25. // does not check the result of memory allocation.
  26. // https://msdn.microsoft.com/en-us/library/het71c37.aspx
  27. // Pass the size of the failed request in an exception argument.
  28. ULONG_PTR exception_args[] = {size};
  29. ::RaiseException(win::kOomExceptionCode, EXCEPTION_NONCONTINUABLE,
  30. std::size(exception_args), exception_args);
  31. // Safety check, make sure process exits here.
  32. _exit(win::kOomExceptionCode);
  33. #else
  34. size_t tmp_size = size;
  35. internal::base::debug::Alias(&tmp_size);
  36. // Note: Don't add anything that may allocate here. Depending on the
  37. // allocator, this may be called from within the allocator (e.g. with
  38. // PartitionAlloc), and would deadlock as our locks are not recursive.
  39. //
  40. // Additionally, this is unlikely to work, since allocating from an OOM
  41. // handler is likely to fail.
  42. //
  43. // Use PA_IMMEDIATE_CRASH() so that the top frame in the crash is our code,
  44. // rather than using abort() or similar; this avoids the crash server needing
  45. // to be able to successfully unwind through libc to get to the correct
  46. // address, which is particularly an issue on Android.
  47. PA_IMMEDIATE_CRASH();
  48. #endif // BUILDFLAG(IS_WIN)
  49. }
  50. } // namespace internal
  51. void TerminateBecauseOutOfMemory(size_t size) {
  52. internal::OnNoMemoryInternal(size);
  53. }
  54. namespace internal {
  55. // The crash is generated in a PA_NOINLINE function so that we can classify the
  56. // crash as an OOM solely by analyzing the stack trace. It is tagged as
  57. // PA_NOT_TAIL_CALLED to ensure that its parent function stays on the stack.
  58. [[noreturn]] PA_NOINLINE void PA_NOT_TAIL_CALLED OnNoMemory(size_t size) {
  59. RunPartitionAllocOomCallback();
  60. TerminateBecauseOutOfMemory(size);
  61. PA_IMMEDIATE_CRASH();
  62. }
  63. } // namespace internal
  64. } // namespace partition_alloc