/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <cstdlib> #include <fcntl.h>
#ifdef _WIN32 # include <windows.h> # include <io.h> # include <process.h> #else # include <unistd.h> # include <pthread.h> #endif
#ifdef ANDROID /* Android doesn't have pthread_atfork defined in pthread.h */ extern"C" MOZ_EXPORT int pthread_atfork(void (*)(void), void (*)(void), void (*)(void)); #endif
class LogAllocBridge : public ReplaceMallocBridge { virtualvoid InitDebugFd(mozilla::DebugFdRegistry& aRegistry) override { if (!sStdoutOrStderr) {
aRegistry.RegisterHandle(sFd);
}
}
};
/* Do a simple, text-form, log of all calls to replace-malloc functions. * Use locking to guarantee that an allocation that did happen is logged * before any other allocation/free happens.
*/
#ifndef _WIN32 /* When another thread has acquired a lock before forking, the child * process will inherit the lock state but the thread, being nonexistent * in the child process, will never release it, leading to a dead-lock * whenever the child process gets the lock. We thus need to ensure no * other thread is holding the lock before forking, by acquiring it * ourselves, and releasing it after forking in the parent process and * resetting it to its initial state in the child process. The latter is * important because some implementations (notably macOS) prevent a lock from * being unlocked by a different thread than the one which locked it in the * first place. * Windows doesn't have this problem since there is no fork(). * The real allocator, however, might be doing the same thing (jemalloc * does). But pthread_atfork `prepare` handlers (first argument) are * processed in reverse order they were established. But replace_init * runs before the real allocator has had any chance to initialize and * call pthread_atfork itself. This leads to its prefork running before * ours. This leads to a race condition that can lead to a deadlock like * the following: * - thread A forks. * - libc calls real allocator's prefork, so thread A holds the real * allocator lock. * - thread B calls malloc, which calls our replace_malloc. * - consequently, thread B holds our lock. * - thread B then proceeds to call the real allocator's malloc, and * waits for the real allocator's lock, which thread A holds. * - libc calls our prefork, so thread A waits for our lock, which * thread B holds. * To avoid this race condition, the real allocator's prefork must be * called after ours, which means it needs to be registered before ours. * So trick the real allocator into initializing itself without more side
* effects by calling malloc with a size it can't possibly allocate. */
sFuncs.malloc(-1);
pthread_atfork(prefork, postfork_parent, postfork_child); #endif
}
¤ Dauer der Verarbeitung: 0.12 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.