• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef LIBMEMUNREACHABLE_SCOPED_DISABLE_MALLOC_H_
18 #define LIBMEMUNREACHABLE_SCOPED_DISABLE_MALLOC_H_
19 
20 #include <memory>
21 
22 #include "android-base/macros.h"
23 
24 #include "ScopedAlarm.h"
25 #include "bionic.h"
26 #include "log.h"
27 
28 namespace android {
29 
30 class DisableMallocGuard {
31  public:
DisableMallocGuard()32   DisableMallocGuard() : disabled_(false) {}
~DisableMallocGuard()33   ~DisableMallocGuard() { Enable(); }
34 
Disable()35   void Disable() {
36     if (!disabled_) {
37       malloc_disable();
38       disabled_ = true;
39     }
40   }
41 
Enable()42   void Enable() {
43     if (disabled_) {
44       malloc_enable();
45       disabled_ = false;
46     }
47   }
48 
49  private:
50   DISALLOW_COPY_AND_ASSIGN(DisableMallocGuard);
51   bool disabled_;
52 };
53 
54 // Any calls to malloc or free from this thread will deadlock as long as this
55 // object is in scope.  Calls to malloc from other threads may succeed (for
56 // example if the allocation is satisfied out of the thread's tcache), or may
57 // block until the object is destroyed.
58 //
59 // Don't call fork() while malloc is disabled, it needs the same locks held
60 // here.
61 class ScopedDisableMalloc {
62  public:
ScopedDisableMalloc()63   ScopedDisableMalloc() { disable_malloc_.Disable(); }
64 
~ScopedDisableMalloc()65   ~ScopedDisableMalloc() { disable_malloc_.Enable(); }
66 
67  private:
68   DISALLOW_COPY_AND_ASSIGN(ScopedDisableMalloc);
69   DisableMallocGuard disable_malloc_;
70 };
71 
72 class ScopedDisableMallocTimeout {
73  public:
74   explicit ScopedDisableMallocTimeout(
75       std::chrono::milliseconds timeout = std::chrono::milliseconds(2000))
timeout_(timeout)76       : timeout_(timeout), timed_out_(false), disable_malloc_() {
77     Disable();
78   }
79 
~ScopedDisableMallocTimeout()80   ~ScopedDisableMallocTimeout() { Enable(); }
81 
timed_out()82   bool timed_out() { return timed_out_; }
83 
Enable()84   void Enable() {
85     disable_malloc_.Enable();
86     alarm_ = nullptr;
87   }
88 
Disable()89   void Disable() {
90     // set up the alarm before disabling malloc so unique_ptr can be used
91     alarm_ = std::make_unique<ScopedAlarm>(timeout_, [&]() {
92       disable_malloc_.Enable();
93       timed_out_ = true;
94     });
95 
96     disable_malloc_.Disable();
97   }
98 
99  private:
100   DISALLOW_COPY_AND_ASSIGN(ScopedDisableMallocTimeout);
101   std::chrono::milliseconds timeout_;
102   bool timed_out_;
103   std::unique_ptr<ScopedAlarm> alarm_;
104   DisableMallocGuard disable_malloc_;
105 };
106 
107 }  // namespace android
108 
109 #endif  // LIBMEMUNREACHABLE_SCOPED_DISABLE_MALLOC_H_
110