Backed out 8 changesets (bug 1918596, bug 1917575, bug 1874689, bug 1925181, bug 1917844, bug 1925274, bug 1915152) for causing failures at Sandbox.cpp. CLOSED TREE

Backed out changeset ce2138248319 (bug 1874689)
Backed out changeset fbe9fbb6ae72 (bug 1925181)
Backed out changeset c9896c8962cb (bug 1925274)
Backed out changeset 6eddbad5949c (bug 1918596)
Backed out changeset b9bf86fa1c74 (bug 1917844)
Backed out changeset 1d4cd83d1a39 (bug 1917844)
Backed out changeset 264a5140fbcb (bug 1917575)
Backed out changeset 87b8512c67c9 (bug 1915152)
This commit is contained in:
Butkovits Atila
2024-10-19 23:27:56 +03:00
parent e74fa95f41
commit 0f3a88d758
14 changed files with 42 additions and 472 deletions

View File

@@ -65,6 +65,16 @@
fun:_Z21XRE_CreateStatsObjectv
...
}
{
We purposely leak forkserver children's new argv strings. (See bug 1878213.)
Memcheck:Leak
match-leak-kinds: definite
fun:malloc
fun:strdup
...
fun:_ZN4base17AppProcessBuilder14InitAppProcessEPiPPPc
...
}
{
We purposely leak copies of the initial argv/environ to implement setproctitle on Linux. (See bug 1878213.)
Memcheck:Leak
@@ -74,14 +84,6 @@
fun:_Z17setproctitle_initPPc
...
}
{
Leak of argv (bug 1925274)
Memcheck:Leak
match-leak-kinds: definite
...
fun:ForkedChildProcessInit
...
}
####################################
# Leaks in third party libraries #

View File

@@ -804,13 +804,6 @@ void ContentChild::Init(mozilla::ipc::UntypedEndpoint&& aEndpoint,
PendingInputEventHangAnnotator::sSingleton);
}));
#endif
#if defined(MOZ_MEMORY) && defined(DEBUG)
jemalloc_stats_t stats;
jemalloc_stats(&stats);
MOZ_ASSERT(!stats.opt_randomize_small,
"Content process should not randomize small allocations");
#endif
}
void ContentChild::AddProfileToProcessName(const nsACString& aProfile) {

View File

@@ -144,45 +144,6 @@ void setproctitle(const char* fmt, ...) {
if (!buggy_kernel && size < argv_size) {
g_argv_end[-1] = '.';
}
const size_t previous_size = g_argv_end - g_argv_start - 1;
ssize_t need_to_save = static_cast<ssize_t>(size - previous_size);
// The argv part has grown so there is less room for the environ part.
// Selectively removing a few environment variables so this can fit.
//
// The goal is trying to make sure that the environment in the
// /proc/PID/environ content for crashes is useful
const char* kEnvSkip[] = {"HOME=", "LS_COLORS=", "PATH=", "XDG_DATA_DIRS="};
const size_t kEnvElems = sizeof(kEnvSkip) / sizeof(kEnvSkip[0]);
size_t environ_size = 0;
for (size_t i = 0; environ[i]; ++i) {
bool skip = false;
const size_t var_size = strlen(environ[i]) + 1;
for (size_t remI = 0; need_to_save > 0 && remI < kEnvElems; ++remI) {
const char* thisEnv = kEnvSkip[remI];
size_t thisEnvSize = sizeof(kEnvSkip[remI]);
int diff = strncmp(environ[i], thisEnv, thisEnvSize);
if (diff == 0) {
need_to_save -= static_cast<ssize_t>(var_size);
skip = true;
break;
}
}
if (skip) {
continue;
}
char* env_start = g_argv_end + environ_size;
if ((env_start + var_size) < g_envp_end) {
const size_t var_size_copied =
snprintf(env_start, var_size, "%s", environ[i]);
environ_size += var_size_copied + 1 /* account for null */;
}
}
}
// A version of this built into glibc would not need this function, since

View File

@@ -205,13 +205,6 @@ bool ForkServer::OnMessageReceived(UniquePtr<IPC::Message> message) {
return false;
}
#if defined(MOZ_MEMORY) && defined(DEBUG)
jemalloc_stats_t stats;
jemalloc_stats(&stats);
MOZ_ASSERT(stats.narenas == 1,
"ForkServer before fork()/clone() should have a single arena.");
#endif
#if defined(XP_LINUX) && defined(MOZ_SANDBOX)
mozilla::SandboxLaunch launcher;
if (!launcher.Prepare(&options)) {
@@ -325,17 +318,6 @@ bool ForkServer::RunForkServer(int* aArgc, char*** aArgv) {
MOZ_ASSERT(!XRE_IsForkServerProcess(),
"fork server created another fork server?");
// This is now a child process, and it may even be a Content process.
// It is required that the PRNG at least is re-initialized so the same state
// is not shared accross all child processes, and in case of a Content process
// it is also required that the small allocation are not being randomized ;
// failing to do so will lead to performance regressions, e.g. as in
// bug 1912262.
#if defined(MOZ_MEMORY)
jemalloc_reset_small_alloc_randomization(
/* aRandomizeSmall */ !XRE_IsContentProcess());
#endif
// Open log files again with right names and the new PID.
nsTraceRefcnt::ReopenLogFilesAfterFork(XRE_GetProcessTypeString());

View File

@@ -138,13 +138,6 @@ bool UtilityProcessImpl::Init(int aArgc, char* aArgv[]) {
return false;
}
#if defined(MOZ_MEMORY) && defined(DEBUG)
jemalloc_stats_t stats;
jemalloc_stats(&stats);
MOZ_ASSERT(stats.opt_randomize_small,
"Utility process should randomize small allocations");
#endif
return mUtility->Init(TakeInitialEndpoint(), nsCString(*parentBuildID),
*sandboxingKind);
}

View File

@@ -114,10 +114,6 @@ MALLOC_DECL(jemalloc_free_dirty_pages, void)
// after lowering the max dirty pages threshold to get RSS back to normal.
MALLOC_DECL(jemalloc_free_excess_dirty_pages, void)
// Change the value of opt_randomize_small to control small allocation
// randomization and maybe perform a reinitialization of the arena's PRNG.
MALLOC_DECL(jemalloc_reset_small_alloc_randomization, void, bool)
// Opt in or out of a thread local arena (bool argument is whether to opt-in
// (true) or out (false)).
MALLOC_DECL(jemalloc_thread_local_arena, void, bool)

View File

@@ -1204,10 +1204,6 @@ struct arena_t {
explicit arena_t(arena_params_t* aParams, bool aIsPrivate);
~arena_t();
void ResetSmallAllocRandomization();
void InitPRNG() MOZ_REQUIRES(mLock);
private:
void InitChunk(arena_chunk_t* aChunk, size_t aMinCommittedPages);
@@ -3395,40 +3391,6 @@ void arena_bin_t::Init(SizeClass aSizeClass) {
mSizeDivisor = FastDivisor<uint16_t>(aSizeClass.Size(), try_run_size);
}
void arena_t::ResetSmallAllocRandomization() {
if (MOZ_UNLIKELY(opt_randomize_small)) {
MaybeMutexAutoLock lock(mLock);
InitPRNG();
}
mRandomizeSmallAllocations = opt_randomize_small;
}
void arena_t::InitPRNG() {
// Both another thread could race and the code backing RandomUint64
// (arc4random for example) may allocate memory while here, so we must
// ensure to start the mPRNG initialization only once and to not hold
// the lock while initializing.
mIsPRNGInitializing = true;
{
mLock.Unlock();
mozilla::Maybe<uint64_t> prngState1 = mozilla::RandomUint64();
mozilla::Maybe<uint64_t> prngState2 = mozilla::RandomUint64();
mLock.Lock();
mozilla::non_crypto::XorShift128PlusRNG prng(prngState1.valueOr(0),
prngState2.valueOr(0));
if (mPRNG) {
*mPRNG = prng;
} else {
void* backing =
base_alloc(sizeof(mozilla::non_crypto::XorShift128PlusRNG));
mPRNG = new (backing)
mozilla::non_crypto::XorShift128PlusRNG(std::move(prng));
}
}
mIsPRNGInitializing = false;
}
void* arena_t::MallocSmall(size_t aSize, bool aZero) {
void* ret;
arena_bin_t* bin;
@@ -3467,7 +3429,25 @@ void* arena_t::MallocSmall(size_t aSize, bool aZero) {
if (MOZ_UNLIKELY(mRandomizeSmallAllocations && mPRNG == nullptr &&
!mIsPRNGInitializing)) {
InitPRNG();
// Both another thread could race and the code backing RandomUint64
// (arc4random for example) may allocate memory while here, so we must
// ensure to start the mPRNG initialization only once and to not hold
// the lock while initializing.
mIsPRNGInitializing = true;
mozilla::non_crypto::XorShift128PlusRNG* prng;
{
// TODO: I think no MaybeMutexAutoUnlock or similar exists, should it?
mLock.Unlock();
mozilla::Maybe<uint64_t> prngState1 = mozilla::RandomUint64();
mozilla::Maybe<uint64_t> prngState2 = mozilla::RandomUint64();
void* backing =
base_alloc(sizeof(mozilla::non_crypto::XorShift128PlusRNG));
prng = new (backing) mozilla::non_crypto::XorShift128PlusRNG(
prngState1.valueOr(0), prngState2.valueOr(0));
mLock.Lock();
}
mPRNG = prng;
mIsPRNGInitializing = false;
}
MOZ_ASSERT(!mRandomizeSmallAllocations || mPRNG);
@@ -4898,7 +4878,6 @@ inline void MozJemalloc::jemalloc_stats_internal(
// Gather runtime settings.
aStats->opt_junk = opt_junk;
aStats->opt_randomize_small = opt_randomize_small;
aStats->opt_zero = opt_zero;
aStats->quantum = kQuantum;
aStats->quantum_max = kMaxQuantumClass;
@@ -5188,40 +5167,6 @@ inline void MozJemalloc::moz_set_max_dirty_page_modifier(int32_t aModifier) {
gArenas.SetDefaultMaxDirtyPageModifier(aModifier);
}
inline void MozJemalloc::jemalloc_reset_small_alloc_randomization(
bool aRandomizeSmall) {
// When this process got forked by ForkServer then it inherited the existing
// state of mozjemalloc. Specifically, parsing of MALLOC_OPTIONS has already
// been done but it may not reflect anymore the current set of options after
// the fork().
//
// Similar behavior is also present on Android where it is also required to
// perform this step.
//
// Content process will have randomization on small malloc disabled via the
// MALLOC_OPTIONS environment variable set by parent process, missing this
// will lead to serious performance regressions because CPU prefetch will
// break, cf bug 1912262. However on forkserver-forked Content processes, the
// environment is not yet reset when the postfork child handler is being
// called.
//
// This API is here to allow those Content processes (spawned by ForkServer or
// Android service) to notify jemalloc to turn off the randomization on small
// allocations and perform the required reinitialization of already existing
// arena's PRNG. It is important to make sure that the PRNG state is properly
// re-initialized otherwise child processes would share all the same state.
{
AutoLock<StaticMutex> lock(gInitLock);
opt_randomize_small = aRandomizeSmall;
}
MutexAutoLock lock(gArenas.mLock);
for (auto* arena : gArenas.iter()) {
arena->ResetSmallAllocRandomization();
}
}
#define MALLOC_DECL(name, return_type, ...) \
inline return_type MozJemalloc::moz_arena_##name( \
arena_id_t aArenaId, ARGS_HELPER(TYPED_ARGS, ##__VA_ARGS__)) { \

View File

@@ -96,19 +96,18 @@ typedef struct arena_params_s {
// file.
typedef struct {
// Run-time configuration settings.
bool opt_junk; // Fill allocated memory with kAllocJunk?
bool opt_randomize_small; // Randomization of small allocations?
bool opt_zero; // Fill allocated memory with 0x0?
size_t narenas; // Number of arenas.
size_t quantum; // Allocation quantum.
size_t quantum_max; // Max quantum-spaced allocation size.
size_t quantum_wide; // Allocation quantum (QuantuWide).
size_t quantum_wide_max; // Max quantum-wide-spaced allocation size.
size_t subpage_max; // Max subpage allocation size.
size_t large_max; // Max sub-chunksize allocation size.
size_t chunksize; // Size of each virtual memory mapping.
size_t page_size; // Size of pages.
size_t dirty_max; // Max dirty pages per arena.
bool opt_junk; // Fill allocated memory with kAllocJunk?
bool opt_zero; // Fill allocated memory with 0x0?
size_t narenas; // Number of arenas.
size_t quantum; // Allocation quantum.
size_t quantum_max; // Max quantum-spaced allocation size.
size_t quantum_wide; // Allocation quantum (QuantuWide).
size_t quantum_wide_max; // Max quantum-wide-spaced allocation size.
size_t subpage_max; // Max subpage allocation size.
size_t large_max; // Max sub-chunksize allocation size.
size_t chunksize; // Size of each virtual memory mapping.
size_t page_size; // Size of pages.
size_t dirty_max; // Max dirty pages per arena.
// Current memory usage statistics.
size_t mapped; // Bytes mapped (not necessarily committed).

View File

@@ -2985,7 +2985,7 @@
#if defined(MOZ_CODE_COVERAGE) || defined(MOZ_ASAN) || defined(MOZ_TSAN) || defined(MOZ_MSAN) || defined(MOZ_UBSAN) || defined(MOZ_PROFILE_GENERATE)
value: false
#else
value: @IS_NIGHTLY_BUILD@
value: false
#endif
mirror: once
#endif

View File

@@ -402,12 +402,6 @@ Java_org_mozilla_gecko_mozglue_GeckoLoader_nativeRun(JNIEnv* jenv, jclass jc,
SetGeckoProcessType(argv[--argc]);
SetGeckoChildID(argv[--argc]);
#if defined(MOZ_MEMORY)
// XRE_IsContentProcess is not accessible here
jemalloc_reset_small_alloc_randomization(
/* aRandomizeSmall */ GetGeckoProcessType() !=
GeckoProcessType_Content);
#endif
gBootstrap->XRE_SetAndroidChildFds(jenv, jfds);
@@ -431,14 +425,8 @@ extern "C" APKOPEN_EXPORT mozglueresult ChildProcessInit(int argc,
if (argc < 2) {
return FAILURE;
}
SetGeckoProcessType(argv[--argc]);
SetGeckoChildID(argv[--argc]);
#if defined(MOZ_MEMORY)
// XRE_IsContentProcess is not accessible here
jemalloc_reset_small_alloc_randomization(
/* aRandomizeSmall */ GetGeckoProcessType() != GeckoProcessType_Content);
#endif
if (loadNSSLibs() != SUCCESS) {
return FAILURE;

View File

@@ -17,15 +17,6 @@ if CONFIG["MOZ_CRASHREPORTER"]:
"pthread_create_interposer.cpp",
]
if CONFIG["MOZ_SANDBOX"]:
EXPORTS.mozilla += [
"pthread_atfork.h",
]
UNIFIED_SOURCES += [
"pthread_atfork_interposer.cpp",
]
if CONFIG["MOZ_LINKER"]:
LOCAL_INCLUDES += [
"/mozglue/linker",

View File

@@ -1,21 +0,0 @@
/* -*- 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/. */
#ifndef __mozilla_pthread_atfork_h_
#define __mozilla_pthread_atfork_h_
#if defined(MOZ_ENABLE_FORKSERVER)
# if defined(__GLIBC__) && !defined(__UCLIBC__)
// We really are using glibc, not uClibc pretending to be glibc.
# define LIBC_GLIBC 1
# endif
extern MFBT_API void run_moz_pthread_atfork_handlers_prefork();
extern MFBT_API void run_moz_pthread_atfork_handlers_postfork_parent();
extern MFBT_API void run_moz_pthread_atfork_handlers_postfork_child();
#endif // defined(MOZ_ENABLE_FORKSERVER)
#endif // __mozilla_pthread_atfork_h_

View File

@@ -1,254 +0,0 @@
/* 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 <atomic>
#include <array>
#include <errno.h>
#include <stdlib.h>
#include "mozilla/Assertions.h"
#include "mozilla/DebugOnly.h"
#include "InterposerHelper.h"
using mozilla::DebugOnly;
#if defined(MOZ_ENABLE_FORKSERVER) && !defined(MOZ_TSAN)
# include "mozilla/pthread_atfork.h"
static constexpr const int maxHandlers = 16;
static constexpr const int idxPreFork = 0;
static constexpr const int idxPostForkParent = 1;
static constexpr const int idxPostForkChild = 2;
struct moz_pthread_atfork_handler {
using fn_ptr = std::atomic<void (*)(void)>;
using dso_handle = std::atomic<void*>;
using pthread_handlers = std::array<fn_ptr, 3>;
std::atomic<int> usedElems = 0;
std::array<pthread_handlers, maxHandlers> handlers = {};
std::array<dso_handle, maxHandlers> dsos = {};
bool add(void (*aPrefork)(void), void (*aParent)(void), void (*aChild)(void),
const void* const aHandle) {
if (usedElems == maxHandlers) {
return false;
}
int elem = 0;
for (elem = 0; elem < maxHandlers; ++elem) {
if (dsos[elem] == nullptr) {
handlers[elem][idxPreFork] = aPrefork;
handlers[elem][idxPostForkParent] = aParent;
handlers[elem][idxPostForkChild] = aChild;
dsos[elem] = (void*)(aHandle);
++usedElems;
break;
}
}
return true;
}
bool remove(void* aHandle) {
int elem = 0;
for (elem = 0; elem < maxHandlers; ++elem) {
if (dsos[elem] == aHandle) {
handlers[elem][idxPreFork] = nullptr;
handlers[elem][idxPostForkParent] = nullptr;
handlers[elem][idxPostForkChild] = nullptr;
dsos[elem] = nullptr;
--usedElems;
}
}
return true;
}
};
struct moz_pthread_atfork_handler mozPthreadHandlers;
# if defined(LIBC_GLIBC)
// On glibc the pthread_atfork may be available only from libc_nonshared.a
// so prefer interposing the linker-resolved __register_atfork()
extern const void* const __dso_handle;
using register_atfork_t = int (*)(void (*)(), void (*)(), void (*)(),
const void* const) noexcept;
static register_atfork_t real_register_atfork = nullptr;
using cxa_finalize_t = void (*)(void*) noexcept;
static cxa_finalize_t real_cxa_finalize = nullptr;
# else
using pthread_atfork_t = int (*)(void (*)(), void (*)(), void (*)()) noexcept;
static pthread_atfork_t real_pthread_atfork = nullptr;
# endif
static int notReadyCount = 0;
extern "C" {
# if defined(LIBC_GLIBC)
MFBT_API int __register_atfork(void (*aPrefork)(void),
void (*aPostForkParent)(void),
void (*aPostForkChild)(void),
const void* const dso_handle)
# else
MFBT_API int pthread_atfork(void (*aPrefork)(void),
void (*aPostForkParent)(void),
void (*aPostForkChild)(void))
# endif
{
# if defined(LIBC_GLIBC)
MOZ_ASSERT(real_register_atfork != __register_atfork,
"Found __register_atfork from libc");
# else
MOZ_ASSERT(real_pthread_atfork != pthread_atfork,
"Found pthread_atfork from libc");
# endif
int rv = 0;
# if defined(LIBC_GLIBC)
if (real_register_atfork) {
real_register_atfork(aPrefork, aPostForkParent, aPostForkChild, dso_handle);
# else
if (real_pthread_atfork) {
real_pthread_atfork(aPrefork, aPostForkParent, aPostForkChild);
# endif
MOZ_ASSERT(rv == 0, "call to real_register_atfork() failed");
if (rv != 0) {
return rv;
}
} else {
++notReadyCount;
}
rv = mozPthreadHandlers.add(aPrefork, aPostForkParent, aPostForkChild
# if defined(LIBC_GLIBC)
,
dso_handle
# endif
)
? 0
: 1;
MOZ_ASSERT(rv == 0,
# if defined(LIBC_GLIBC)
"Should have been able to add to __register_atfork() handlers"
# else
"Should have been able to add to pthread_atfork() handlers"
# endif
);
if (rv > 0) {
rv = ENOMEM;
}
return rv;
}
# if defined(LIBC_GLIBC)
MFBT_API void __cxa_finalize(void* handle) {
real_cxa_finalize(handle);
mozPthreadHandlers.remove(handle);
}
# endif
}
# if defined(LIBC_GLIBC)
__attribute__((used)) __attribute__((constructor)) void register_atfork_setup(
void) {
const char* glibc_version_register =
# if defined(__x86_64__) || defined(__i386__)
"GLIBC_2.3.2"
# elif defined(__aarch64__)
"GLIBC_2.17"
# else
# error \
"Missing GLIBC version for __register_atfork(). Please objdump -tTC libc.so.6 and add"
# endif
;
// Use dlvsym() otherwise symbol resolution may find the interposed version
real_register_atfork = (register_atfork_t)dlvsym(nullptr, "__register_atfork",
glibc_version_register);
MOZ_ASSERT(real_register_atfork != nullptr, "Found real_register_atfork");
MOZ_ASSERT(real_register_atfork != __register_atfork,
"Found register_atfork from libc");
const char* glibc_version_finalize =
# if defined(__i386__)
"GLIBC_2.1.3"
# elif defined(__x86_64__)
"GLIBC_2.2.5"
# elif defined(__aarch64__)
"GLIBC_2.17"
# else
# error \
"Missing GLIBC version for __cxa_finalize(). Please objdump -tTC libc.so.6 and add"
# endif
;
// Use dlvsym() otherwise symbol resolution may find the interposed version
real_cxa_finalize =
(cxa_finalize_t)dlvsym(nullptr, "__cxa_finalize", glibc_version_finalize);
MOZ_ASSERT(real_cxa_finalize != nullptr, "Found real_cxa_finalize");
MOZ_ASSERT(real_cxa_finalize != __cxa_finalize,
"Found cxa_finalize from libc");
if (notReadyCount > 0) {
for (int i = 0; i < notReadyCount; ++i) {
real_register_atfork(mozPthreadHandlers.handlers[i][idxPreFork],
mozPthreadHandlers.handlers[i][idxPostForkParent],
mozPthreadHandlers.handlers[i][idxPostForkChild],
__dso_handle);
}
}
}
# else
__attribute__((used)) __attribute__((constructor)) void pthread_atfork_setup(
void) {
real_pthread_atfork = (pthread_atfork_t)dlsym(RTLD_NEXT, "pthread_atfork");
MOZ_ASSERT(real_pthread_atfork != nullptr, "Found real_pthread_atfork");
MOZ_ASSERT(real_pthread_atfork != pthread_atfork,
"Found pthread_atfork from libc");
if (notReadyCount > 0) {
for (int i = 0; i < notReadyCount; ++i) {
real_pthread_atfork(mozPthreadHandlers.handlers[i][idxPreFork],
mozPthreadHandlers.handlers[i][idxPostForkParent],
mozPthreadHandlers.handlers[i][idxPostForkChild]);
}
}
}
# endif
void run_moz_pthread_atfork_handlers(struct moz_pthread_atfork_handler* list,
int handlerIdx, bool reverse) {
MOZ_ASSERT(list, "moz_pthread_atfork_handler should not be nullptr");
for (int i = (reverse ? maxHandlers - 1 : 0);
(reverse ? (i >= 0) : (i < maxHandlers)); (reverse ? --i : ++i)) {
if (list->dsos[i]) {
if (list->handlers[i][handlerIdx]) {
(*list->handlers[i][handlerIdx])();
}
}
}
}
void run_moz_pthread_atfork_handlers_prefork() {
run_moz_pthread_atfork_handlers(&mozPthreadHandlers, idxPreFork, true);
}
void run_moz_pthread_atfork_handlers_postfork_parent() {
run_moz_pthread_atfork_handlers(&mozPthreadHandlers, idxPostForkParent,
false);
}
void run_moz_pthread_atfork_handlers_postfork_child() {
run_moz_pthread_atfork_handlers(&mozPthreadHandlers, idxPostForkChild, false);
}
#endif // defined(MOZ_ENABLE_FORKSERVER)

View File

@@ -45,8 +45,6 @@
#include "sandbox/linux/system_headers/linux_syscalls.h"
#include "sandbox/linux/services/syscall_wrappers.h"
#include "mozilla/pthread_atfork.h"
#ifdef MOZ_X11
# ifndef MOZ_WIDGET_GTK
# error "Unknown toolkit"
@@ -625,14 +623,11 @@ pid_t SandboxLaunch::Fork() {
// can't run atfork hooks.)
sigset_t oldSigs;
BlockAllSignals(&oldSigs);
run_moz_pthread_atfork_handlers_prefork();
pid_t pid = ForkWithFlags(mFlags);
if (pid != 0) {
run_moz_pthread_atfork_handlers_postfork_parent();
RestoreSignals(&oldSigs);
return pid;
}
run_moz_pthread_atfork_handlers_postfork_child();
// WARNING: all code from this point on (and in StartChrootServer)
// must be async signal safe. In particular, it cannot do anything