mirror of
https://github.com/chromium/crashpad.git
synced 2025-03-10 14:46:07 +00:00
Stop the prune thread and the upload thread when moving to the inactive/background state. This will reduce the number of 0xdead10cc system kills from having a file lock during iOS suspend. Wait to start the prune thread when the application is active. Otherwise, for iOS prewarmed applications, the prune thread will regularly start when the application is foregrounded for the first time when the user intentionally runs the app. It's still possible for either the prune thread or the upload thread to have a file lock during iOS suspend, such as when a task started in the foreground and does not complete in time for suspension. Future work should include considering BackgroundTasks and/or NSURLSessions, which can more safely run in the background. Bug: crashpad: 400 Change-Id: Ic7d4687eb795fe585327f128aa84a5928141f4a9 Reviewed-on: https://chromium-review.googlesource.com/c/crashpad/crashpad/+/3517967 Reviewed-by: Robert Sesek <rsesek@chromium.org> Commit-Queue: Justin Cohen <justincohen@chromium.org>
230 lines
7.6 KiB
Plaintext
230 lines
7.6 KiB
Plaintext
// Copyright 2020 The Crashpad Authors. All rights reserved.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
#include "util/ios/ios_system_data_collector.h"
|
|
|
|
#include <sys/sysctl.h>
|
|
#include <sys/utsname.h>
|
|
|
|
#import <Foundation/Foundation.h>
|
|
#include <TargetConditionals.h>
|
|
#import <UIKit/UIKit.h>
|
|
|
|
#include "base/mac/mach_logging.h"
|
|
#include "base/numerics/safe_conversions.h"
|
|
#include "base/strings/stringprintf.h"
|
|
#include "base/strings/sys_string_conversions.h"
|
|
#include "build/build_config.h"
|
|
|
|
namespace {
|
|
|
|
std::string ReadStringSysctlByName(const char* name) {
|
|
size_t buf_len;
|
|
if (sysctlbyname(name, nullptr, &buf_len, nullptr, 0) != 0) {
|
|
PLOG(WARNING) << "sysctlbyname (size) " << name;
|
|
return std::string();
|
|
}
|
|
|
|
if (buf_len == 0) {
|
|
return std::string();
|
|
}
|
|
|
|
std::string value(buf_len - 1, '\0');
|
|
if (sysctlbyname(name, &value[0], &buf_len, nullptr, 0) != 0) {
|
|
PLOG(WARNING) << "sysctlbyname " << name;
|
|
return std::string();
|
|
}
|
|
|
|
return value;
|
|
}
|
|
|
|
template <typename T, void (T::*M)(void)>
|
|
void AddObserver(CFStringRef notification_name, T* observer) {
|
|
CFNotificationCenterAddObserver(
|
|
CFNotificationCenterGetLocalCenter(),
|
|
observer,
|
|
[](CFNotificationCenterRef center,
|
|
void* observer_vp,
|
|
CFNotificationName name,
|
|
const void* object,
|
|
CFDictionaryRef userInfo) {
|
|
T* observer = reinterpret_cast<T*>(observer_vp);
|
|
(observer->*M)();
|
|
},
|
|
notification_name,
|
|
nullptr,
|
|
CFNotificationSuspensionBehaviorDeliverImmediately);
|
|
}
|
|
|
|
} // namespace
|
|
|
|
namespace crashpad {
|
|
namespace internal {
|
|
|
|
IOSSystemDataCollector::IOSSystemDataCollector()
|
|
: major_version_(0),
|
|
minor_version_(0),
|
|
patch_version_(0),
|
|
build_(),
|
|
machine_description_(),
|
|
orientation_(0),
|
|
processor_count_(0),
|
|
cpu_vendor_(),
|
|
has_next_daylight_saving_time_(false),
|
|
is_daylight_saving_time_(false),
|
|
standard_offset_seconds_(0),
|
|
daylight_offset_seconds_(0),
|
|
standard_name_(),
|
|
daylight_name_() {
|
|
NSOperatingSystemVersion version =
|
|
[[NSProcessInfo processInfo] operatingSystemVersion];
|
|
major_version_ = base::saturated_cast<int>(version.majorVersion);
|
|
minor_version_ = base::saturated_cast<int>(version.minorVersion);
|
|
patch_version_ = base::saturated_cast<int>(version.patchVersion);
|
|
processor_count_ =
|
|
base::saturated_cast<int>([[NSProcessInfo processInfo] processorCount]);
|
|
build_ = ReadStringSysctlByName("kern.osversion");
|
|
bundle_identifier_ =
|
|
base::SysNSStringToUTF8([[NSBundle mainBundle] bundleIdentifier]);
|
|
is_extension_ = [[NSBundle mainBundle].bundlePath hasSuffix:@"appex"];
|
|
|
|
#if defined(ARCH_CPU_X86_64)
|
|
cpu_vendor_ = ReadStringSysctlByName("machdep.cpu.vendor");
|
|
#endif
|
|
|
|
#if TARGET_OS_SIMULATOR
|
|
// TODO(justincohen): Consider adding board and model information to
|
|
// |machine_description| as well (similar to MacModelAndBoard in
|
|
// util/mac/mac_util.cc).
|
|
const char* model = getenv("SIMULATOR_MODEL_IDENTIFIER");
|
|
if (model == nullptr) {
|
|
switch ([[UIDevice currentDevice] userInterfaceIdiom]) {
|
|
case UIUserInterfaceIdiomPhone:
|
|
model = "iPhone";
|
|
break;
|
|
case UIUserInterfaceIdiomPad:
|
|
model = "iPad";
|
|
break;
|
|
default:
|
|
model = "Unknown";
|
|
break;
|
|
}
|
|
}
|
|
machine_description_ = base::StringPrintf("iOS Simulator (%s)", model);
|
|
#elif TARGET_OS_IPHONE
|
|
utsname uts;
|
|
if (uname(&uts) == 0) {
|
|
machine_description_ = uts.machine;
|
|
}
|
|
#else
|
|
#error "Unexpected target type OS."
|
|
#endif
|
|
|
|
InstallHandlers();
|
|
}
|
|
|
|
IOSSystemDataCollector::~IOSSystemDataCollector() {
|
|
CFNotificationCenterRemoveEveryObserver(CFNotificationCenterGetLocalCenter(),
|
|
this);
|
|
}
|
|
|
|
void IOSSystemDataCollector::OSVersion(int* major,
|
|
int* minor,
|
|
int* bugfix) const {
|
|
*major = major_version_;
|
|
*minor = minor_version_;
|
|
*bugfix = patch_version_;
|
|
}
|
|
|
|
void IOSSystemDataCollector::InstallHandlers() {
|
|
// Timezone.
|
|
AddObserver<IOSSystemDataCollector,
|
|
&IOSSystemDataCollector::SystemTimeZoneDidChangeNotification>(
|
|
(__bridge CFStringRef)NSSystemTimeZoneDidChangeNotification, this);
|
|
SystemTimeZoneDidChangeNotification();
|
|
|
|
// Orientation.
|
|
AddObserver<IOSSystemDataCollector,
|
|
&IOSSystemDataCollector::OrientationDidChangeNotification>(
|
|
(__bridge CFStringRef)UIDeviceOrientationDidChangeNotification, this);
|
|
OrientationDidChangeNotification();
|
|
|
|
// Foreground/Background. Extensions shouldn't use UIApplication*.
|
|
if (!is_extension_) {
|
|
AddObserver<
|
|
IOSSystemDataCollector,
|
|
&IOSSystemDataCollector::ApplicationDidChangeActiveNotification>(
|
|
(__bridge CFStringRef)UIApplicationDidBecomeActiveNotification, this);
|
|
AddObserver<
|
|
IOSSystemDataCollector,
|
|
&IOSSystemDataCollector::ApplicationDidChangeActiveNotification>(
|
|
(__bridge CFStringRef)UIApplicationDidEnterBackgroundNotification,
|
|
this);
|
|
ApplicationDidChangeActiveNotification();
|
|
}
|
|
}
|
|
|
|
void IOSSystemDataCollector::SystemTimeZoneDidChangeNotification() {
|
|
NSTimeZone* time_zone = NSTimeZone.localTimeZone;
|
|
NSDate* transition =
|
|
[time_zone nextDaylightSavingTimeTransitionAfterDate:[NSDate date]];
|
|
if (transition == nil) {
|
|
has_next_daylight_saving_time_ = false;
|
|
is_daylight_saving_time_ = false;
|
|
standard_offset_seconds_ =
|
|
base::saturated_cast<int>([time_zone secondsFromGMTForDate:transition]);
|
|
standard_name_ = base::SysNSStringToUTF8([time_zone abbreviation]);
|
|
daylight_offset_seconds_ = standard_offset_seconds_;
|
|
daylight_name_ = standard_name_;
|
|
} else {
|
|
has_next_daylight_saving_time_ = true;
|
|
is_daylight_saving_time_ = time_zone.isDaylightSavingTime;
|
|
if (time_zone.isDaylightSavingTime) {
|
|
standard_offset_seconds_ = base::saturated_cast<int>(
|
|
[time_zone secondsFromGMTForDate:transition]);
|
|
standard_name_ =
|
|
base::SysNSStringToUTF8([time_zone abbreviationForDate:transition]);
|
|
daylight_offset_seconds_ =
|
|
base::saturated_cast<int>([time_zone secondsFromGMT]);
|
|
daylight_name_ = base::SysNSStringToUTF8([time_zone abbreviation]);
|
|
} else {
|
|
standard_offset_seconds_ =
|
|
base::saturated_cast<int>([time_zone secondsFromGMT]);
|
|
standard_name_ = base::SysNSStringToUTF8([time_zone abbreviation]);
|
|
daylight_offset_seconds_ = base::saturated_cast<int>(
|
|
[time_zone secondsFromGMTForDate:transition]);
|
|
daylight_name_ =
|
|
base::SysNSStringToUTF8([time_zone abbreviationForDate:transition]);
|
|
}
|
|
}
|
|
}
|
|
|
|
void IOSSystemDataCollector::OrientationDidChangeNotification() {
|
|
orientation_ =
|
|
base::saturated_cast<int>([[UIDevice currentDevice] orientation]);
|
|
}
|
|
|
|
void IOSSystemDataCollector::ApplicationDidChangeActiveNotification() {
|
|
dispatch_assert_queue_debug(dispatch_get_main_queue());
|
|
bool old_active = active_;
|
|
active_ = [UIApplication sharedApplication].applicationState ==
|
|
UIApplicationStateActive;
|
|
if (active_ != old_active && active_application_callback_) {
|
|
active_application_callback_(active_);
|
|
}
|
|
}
|
|
|
|
} // namespace internal
|
|
} // namespace crashpad
|