зеркало из https://github.com/mozilla/gecko-dev.git
Backed out 2 changesets (bug 1678152, bug 1751041) for causing failures in test_missing_intermediate.js CLOSED TREE
Backed out changeset 034ae0e4c467 (bug 1751041) Backed out changeset 46640f068ae4 (bug 1678152)
This commit is contained in:
Родитель
c07c87c034
Коммит
f471472a6b
|
@ -760,7 +760,7 @@ void APZCTreeManager::SampleForWebRender(const Maybe<VsyncId>& aVsyncId,
|
|||
it->second->RecordSampledResult(
|
||||
apzc->GetCurrentAsyncScrollOffsetInCssPixels(
|
||||
AsyncPanZoomController::eForCompositing),
|
||||
(aSampleTime.Time() - TimeStamp::ProcessCreation())
|
||||
(aSampleTime.Time() - TimeStamp::ProcessCreation(nullptr))
|
||||
.ToMicroseconds(),
|
||||
guid.mLayersId, guid.mScrollId);
|
||||
}
|
||||
|
|
|
@ -36,29 +36,7 @@ struct TimeStampInitialization {
|
|||
|
||||
TimeStampInitialization() {
|
||||
TimeStamp::Startup();
|
||||
TimeStamp now = TimeStamp::Now();
|
||||
|
||||
TimeStamp process_creation;
|
||||
char* mozAppRestart = getenv("MOZ_APP_RESTART");
|
||||
|
||||
/* When calling PR_SetEnv() with an empty value the existing variable may
|
||||
* be unset or set to the empty string depending on the underlying platform
|
||||
* thus we have to check if the variable is present and not empty. */
|
||||
if (mozAppRestart && (strcmp(mozAppRestart, "") != 0)) {
|
||||
process_creation = now;
|
||||
} else {
|
||||
uint64_t uptime = TimeStamp::ComputeProcessUptime();
|
||||
process_creation =
|
||||
now - TimeDuration::FromMicroseconds(static_cast<double>(uptime));
|
||||
|
||||
if ((process_creation > now) || (uptime == 0)) {
|
||||
process_creation = now;
|
||||
}
|
||||
}
|
||||
|
||||
mFirstTimeStamp = now;
|
||||
mProcessCreation = process_creation;
|
||||
|
||||
mFirstTimeStamp = TimeStamp::Now();
|
||||
// On Windows < 10, initializing the uptime requires `mFirstTimeStamp` to be
|
||||
// valid.
|
||||
mozilla::InitializeUptime();
|
||||
|
@ -69,12 +47,47 @@ struct TimeStampInitialization {
|
|||
|
||||
static TimeStampInitialization sInitOnce;
|
||||
|
||||
MFBT_API TimeStamp TimeStamp::ProcessCreation() {
|
||||
MFBT_API TimeStamp TimeStamp::ProcessCreation(bool* aIsInconsistent) {
|
||||
if (aIsInconsistent) {
|
||||
*aIsInconsistent = false;
|
||||
}
|
||||
|
||||
if (sInitOnce.mProcessCreation.IsNull()) {
|
||||
char* mozAppRestart = getenv("MOZ_APP_RESTART");
|
||||
TimeStamp ts;
|
||||
|
||||
/* When calling PR_SetEnv() with an empty value the existing variable may
|
||||
* be unset or set to the empty string depending on the underlying platform
|
||||
* thus we have to check if the variable is present and not empty. */
|
||||
if (mozAppRestart && (strcmp(mozAppRestart, "") != 0)) {
|
||||
/* Firefox was restarted, use the first time-stamp we've taken as the new
|
||||
* process startup time. */
|
||||
ts = sInitOnce.mFirstTimeStamp;
|
||||
} else {
|
||||
TimeStamp now = Now();
|
||||
uint64_t uptime = ComputeProcessUptime();
|
||||
|
||||
ts = now - TimeDuration::FromMicroseconds(uptime);
|
||||
|
||||
if ((ts > sInitOnce.mFirstTimeStamp) || (uptime == 0)) {
|
||||
/* If the process creation timestamp was inconsistent replace it with
|
||||
* the first one instead and notify that a telemetry error was
|
||||
* detected. */
|
||||
if (aIsInconsistent) {
|
||||
*aIsInconsistent = true;
|
||||
}
|
||||
ts = sInitOnce.mFirstTimeStamp;
|
||||
}
|
||||
}
|
||||
|
||||
sInitOnce.mProcessCreation = ts;
|
||||
}
|
||||
|
||||
return sInitOnce.mProcessCreation;
|
||||
}
|
||||
|
||||
void TimeStamp::RecordProcessRestart() {
|
||||
sInitOnce.mProcessCreation = TimeStamp::Now();
|
||||
sInitOnce.mProcessCreation = TimeStamp();
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -7,14 +7,14 @@
|
|||
#ifndef mozilla_TimeStamp_h
|
||||
#define mozilla_TimeStamp_h
|
||||
|
||||
#include <stdint.h>
|
||||
#include <algorithm> // for std::min, std::max
|
||||
#include <ostream>
|
||||
#include <type_traits>
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/FloatingPoint.h"
|
||||
#include "mozilla/Types.h"
|
||||
#include <algorithm> // for std::min, std::max
|
||||
#include <ostream>
|
||||
#include <stdint.h>
|
||||
#include <type_traits>
|
||||
|
||||
namespace IPC {
|
||||
template <typename T>
|
||||
|
@ -422,11 +422,16 @@ class TimeStamp {
|
|||
/**
|
||||
* Return a timestamp representing the time when the current process was
|
||||
* created which will be comparable with other timestamps taken with this
|
||||
* class.
|
||||
* class. If the actual process creation time is detected to be inconsistent
|
||||
* the @a aIsInconsistent parameter will be set to true, the returned
|
||||
* timestamp however will still be valid though inaccurate.
|
||||
*
|
||||
* @returns A timestamp representing the time when the process was created
|
||||
* @param aIsInconsistent If non-null, set to true if an inconsistency was
|
||||
* detected in the process creation time
|
||||
* @returns A timestamp representing the time when the process was created,
|
||||
* this timestamp is always valid even when errors are reported
|
||||
*/
|
||||
static MFBT_API TimeStamp ProcessCreation();
|
||||
static MFBT_API TimeStamp ProcessCreation(bool* aIsInconsistent = nullptr);
|
||||
|
||||
/**
|
||||
* Records a process restart. After this call ProcessCreation() will return
|
||||
|
@ -526,10 +531,8 @@ class TimeStamp {
|
|||
|
||||
private:
|
||||
friend struct IPC::ParamTraits<mozilla::TimeStamp>;
|
||||
friend struct TimeStampInitialization;
|
||||
|
||||
MOZ_IMPLICIT
|
||||
TimeStamp(TimeStampValue aValue) : mValue(aValue) {}
|
||||
MOZ_IMPLICIT TimeStamp(TimeStampValue aValue) : mValue(aValue) {}
|
||||
|
||||
static MFBT_API TimeStamp Now(bool aHighResolution);
|
||||
|
||||
|
|
|
@ -42,7 +42,8 @@ static nsReturnRef<HANDLE> CreateProcessWrapper(const wchar_t* aPath) {
|
|||
int ChildMain() {
|
||||
// Make sure a process creation timestamp is always not bigger than
|
||||
// the current timestamp.
|
||||
auto t0 = mozilla::TimeStamp::ProcessCreation();
|
||||
bool inconsistent = false;
|
||||
auto t0 = mozilla::TimeStamp::ProcessCreation(&inconsistent);
|
||||
auto t1 = mozilla::TimeStamp::Now();
|
||||
if (t0 > t1) {
|
||||
printf(
|
||||
|
|
|
@ -45,11 +45,14 @@ void StartupTimeline::RecordOnce(Event ev, const TimeStamp& aWhen) {
|
|||
|
||||
// Record first paint timestamp as a scalar.
|
||||
if (ev == FIRST_PAINT || ev == FIRST_PAINT2) {
|
||||
bool error = false;
|
||||
uint32_t firstPaintTime =
|
||||
(uint32_t)(aWhen - TimeStamp::ProcessCreation()).ToMilliseconds();
|
||||
Telemetry::ScalarSet(ev == FIRST_PAINT
|
||||
? Telemetry::ScalarID::TIMESTAMPS_FIRST_PAINT
|
||||
: Telemetry::ScalarID::TIMESTAMPS_FIRST_PAINT_TWO,
|
||||
firstPaintTime);
|
||||
(uint32_t)(aWhen - TimeStamp::ProcessCreation(&error)).ToMilliseconds();
|
||||
if (!error) {
|
||||
Telemetry::ScalarSet(
|
||||
ev == FIRST_PAINT ? Telemetry::ScalarID::TIMESTAMPS_FIRST_PAINT
|
||||
: Telemetry::ScalarID::TIMESTAMPS_FIRST_PAINT_TWO,
|
||||
firstPaintTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -823,7 +823,9 @@ nsAppStartup::GetStartupInfo(JSContext* aCx,
|
|||
TimeStamp procTime = StartupTimeline::Get(StartupTimeline::PROCESS_CREATION);
|
||||
|
||||
if (procTime.IsNull()) {
|
||||
procTime = TimeStamp::ProcessCreation();
|
||||
bool error = false;
|
||||
|
||||
procTime = TimeStamp::ProcessCreation(&error);
|
||||
|
||||
StartupTimeline::Record(StartupTimeline::PROCESS_CREATION, procTime);
|
||||
}
|
||||
|
|
|
@ -53,7 +53,6 @@ if CONFIG["MOZ_CRASHREPORTER"]:
|
|||
"google-breakpad/src/common",
|
||||
"google-breakpad/src/common/linux",
|
||||
"google-breakpad/src/processor",
|
||||
"pthread_create_interposer",
|
||||
]
|
||||
|
||||
if CONFIG["MOZ_OXIDIZED_BREAKPAD"]:
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# 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/.
|
||||
NoVisibilityFlags()
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
"pthread_create_interposer.cpp",
|
||||
]
|
||||
|
||||
FINAL_LIBRARY = "mozglue"
|
|
@ -1,119 +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 <algorithm>
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/DebugOnly.h"
|
||||
|
||||
using mozilla::DebugOnly;
|
||||
|
||||
struct PthreadCreateParams {
|
||||
void* (*start_routine)(void*);
|
||||
void* arg;
|
||||
};
|
||||
|
||||
const size_t kSigStackSize = std::max(size_t(16384), size_t(SIGSTKSZ));
|
||||
|
||||
// Install the alternate signal stack, returns a pointer to the memory area we
|
||||
// mapped to store the stack only if it was installed successfully, otherwise
|
||||
// returns NULL.
|
||||
static void* install_sig_alt_stack() {
|
||||
void* alt_stack_mem = mmap(nullptr, kSigStackSize, PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
if (alt_stack_mem) {
|
||||
stack_t alt_stack = {
|
||||
.ss_sp = alt_stack_mem,
|
||||
.ss_flags = 0,
|
||||
.ss_size = kSigStackSize,
|
||||
};
|
||||
|
||||
int rv = sigaltstack(&alt_stack, nullptr);
|
||||
if (rv == 0) {
|
||||
return alt_stack_mem;
|
||||
}
|
||||
|
||||
rv = munmap(alt_stack_mem, kSigStackSize);
|
||||
MOZ_ASSERT(rv == 0);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Uninstall the alternate signal handler and unmaps it. Does nothing if
|
||||
// alt_stack_mem is NULL.
|
||||
static void uninstall_sig_alt_stack(void* alt_stack_mem) {
|
||||
if (alt_stack_mem) {
|
||||
stack_t disable_alt_stack = {};
|
||||
disable_alt_stack.ss_flags = SS_DISABLE;
|
||||
DebugOnly<int> rv = sigaltstack(&disable_alt_stack, nullptr);
|
||||
MOZ_ASSERT(rv == 0);
|
||||
rv = munmap(alt_stack_mem, kSigStackSize);
|
||||
MOZ_ASSERT(rv == 0);
|
||||
}
|
||||
}
|
||||
|
||||
// This replaces the routine passed to pthread_create() when a thread is
|
||||
// started, it handles the alternate signal stack and calls the thread's
|
||||
// actual routine.
|
||||
void* set_alt_signal_stack_and_start(PthreadCreateParams* params) {
|
||||
void* (*start_routine)(void*) = params->start_routine;
|
||||
void* arg = params->arg;
|
||||
free(params);
|
||||
|
||||
void* thread_rv = nullptr;
|
||||
void* alt_stack_mem = install_sig_alt_stack();
|
||||
pthread_cleanup_push(uninstall_sig_alt_stack, alt_stack_mem);
|
||||
thread_rv = start_routine(arg);
|
||||
pthread_cleanup_pop(1);
|
||||
|
||||
return thread_rv;
|
||||
}
|
||||
|
||||
using pthread_create_func_t = int (*)(pthread_t*, const pthread_attr_t*,
|
||||
void* (*)(void*), void*);
|
||||
|
||||
extern "C" {
|
||||
// This interposer replaces libpthread's pthread_create() so that we can
|
||||
// inject an alternate signal stack in every new thread.
|
||||
__attribute__((visibility("default"))) int pthread_create(
|
||||
pthread_t* thread, const pthread_attr_t* attr,
|
||||
void* (*start_routine)(void*), void* arg) {
|
||||
// static const pthread_create_func_t real_pthread_create =
|
||||
static const pthread_create_func_t real_pthread_create =
|
||||
(pthread_create_func_t)dlsym(RTLD_NEXT, "pthread_create");
|
||||
|
||||
if (real_pthread_create == nullptr) {
|
||||
MOZ_CRASH(
|
||||
"pthread_create() interposition failed but the interposer function is "
|
||||
"still being called, this won't work!");
|
||||
}
|
||||
|
||||
if (real_pthread_create == pthread_create) {
|
||||
MOZ_CRASH(
|
||||
"We could not obtain the real pthread_create(). Calling the symbol we "
|
||||
"got would make us enter an infinte loop so stop here instead.");
|
||||
}
|
||||
|
||||
PthreadCreateParams* params =
|
||||
(PthreadCreateParams*)malloc(sizeof(PthreadCreateParams));
|
||||
params->start_routine = start_routine;
|
||||
params->arg = arg;
|
||||
|
||||
int result = real_pthread_create(
|
||||
thread, attr, (void* (*)(void*))set_alt_signal_stack_and_start, params);
|
||||
|
||||
if (result != 0) {
|
||||
free(params);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
|
@ -36,7 +36,6 @@ var CrashTestUtils = {
|
|||
CRASH_PHC_BOUNDS_VIOLATION: 23,
|
||||
CRASH_HEAP_CORRUPTION: 24,
|
||||
CRASH_EXC_GUARD: 25,
|
||||
CRASH_STACK_OVERFLOW: 26,
|
||||
|
||||
// Constants for dumpHasStream()
|
||||
// From google_breakpad/common/minidump_format.h
|
||||
|
|
|
@ -97,7 +97,6 @@ const int16_t CRASH_PHC_DOUBLE_FREE = 22;
|
|||
const int16_t CRASH_PHC_BOUNDS_VIOLATION = 23;
|
||||
const int16_t CRASH_HEAP_CORRUPTION = 24;
|
||||
const int16_t CRASH_EXC_GUARD = 25;
|
||||
const int16_t CRASH_STACK_OVERFLOW = 26;
|
||||
|
||||
#if XP_WIN && HAVE_64BIT_BUILD && defined(_M_X64) && !defined(__MINGW32__)
|
||||
|
||||
|
@ -154,23 +153,6 @@ uint8_t* GetPHCAllocation(size_t aSize) {
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifndef XP_WIN
|
||||
static void* overflow_stack(void* aUnused) {
|
||||
// We use a dummy variable and a bit of magic to pretend we care about what's
|
||||
// on the stack so the compiler doesn't optimize the loop and allocations away
|
||||
void* rv = nullptr;
|
||||
|
||||
for (size_t i = 0; i < 1024 * 1024 * 1024; i++) {
|
||||
void* ptr = alloca(sizeof(void*));
|
||||
if (ptr != nullptr) {
|
||||
rv = ptr;
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
#endif // XP_WIN
|
||||
|
||||
extern "C" NS_EXPORT void Crash(int16_t how) {
|
||||
switch (how) {
|
||||
case CRASH_INVALID_POINTER_DEREF: {
|
||||
|
@ -283,17 +265,6 @@ extern "C" NS_EXPORT void Crash(int16_t how) {
|
|||
}
|
||||
}
|
||||
#endif // XP_MACOSX
|
||||
#ifndef XP_WIN
|
||||
case CRASH_STACK_OVERFLOW: {
|
||||
pthread_t thread_id;
|
||||
int rv = pthread_create(&thread_id, nullptr, overflow_stack, nullptr);
|
||||
if (!rv) {
|
||||
pthread_join(thread_id, nullptr);
|
||||
}
|
||||
|
||||
break; // This should be unreachable
|
||||
}
|
||||
#endif // XP_WIN
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
add_task(async function run_test() {
|
||||
if (!("@mozilla.org/toolkit/crash-reporter;1" in Cc)) {
|
||||
dump(
|
||||
"INFO | test_crash_stack_overflow.js | Can't test crashreporter in a non-libxul build.\n"
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Try crashing by overflowing a thread's stack
|
||||
await do_crash(
|
||||
function() {
|
||||
crashType = CrashTestUtils.CRASH_STACK_OVERFLOW;
|
||||
crashReporter.annotateCrashReport("TestKey", "TestValue");
|
||||
},
|
||||
async function(mdump, extra, extraFile) {
|
||||
Assert.equal(extra.TestKey, "TestValue");
|
||||
},
|
||||
// process will exit with a zero exit status
|
||||
true
|
||||
);
|
||||
});
|
|
@ -124,6 +124,3 @@ skip-if = !(os == 'win' && bits == 64 && processor == 'x86_64')
|
|||
reason = Windows test specific to the x86-64 architecture
|
||||
support-files = test_crash_win64cfi_not_a_pe.exe
|
||||
|
||||
[test_crash_stack_overflow.js]
|
||||
skip-if = os != 'linux'
|
||||
reason = Still broken on macOS and not yet supported on Windows
|
||||
|
|
|
@ -41,7 +41,11 @@ void SchedulerGroup::MarkVsyncReceived() {
|
|||
// May be called on any thread when a vsync is received and scheduled to be
|
||||
// processed. This may occur on the main thread due to queued messages when
|
||||
// the channel is connected.
|
||||
TimeStamp creation = TimeStamp::ProcessCreation();
|
||||
bool inconsistent = false;
|
||||
TimeStamp creation = TimeStamp::ProcessCreation(&inconsistent);
|
||||
if (inconsistent) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Attempt to set gEarliestUnprocessedVsync to our new value. If we've seen a
|
||||
// vsync already, but haven't handled it, the `compareExchange` will fail and
|
||||
|
|
Загрузка…
Ссылка в новой задаче