-
Notifications
You must be signed in to change notification settings - Fork 4.3k
Resolve Linux Warning & Improve Windows Debugging #13274
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
@@ -1,22 +1,158 @@ | ||||||||||
/**************************************************************************** | ||||||||||
* | ||||||||||
* (c) 2009-2024 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org> | ||||||||||
* | ||||||||||
* QGroundControl is licensed according to the terms in the file | ||||||||||
* COPYING.md in the root of the source code directory. | ||||||||||
* | ||||||||||
****************************************************************************/ | ||||||||||
|
||||||||||
#include "Platform.h" | ||||||||||
|
||||||||||
#ifdef Q_OS_MAC | ||||||||||
#include <CoreFoundation/CoreFoundation.h> | ||||||||||
#include <QtCore/QCoreApplication> | ||||||||||
#include <QtCore/QProcessEnvironment> | ||||||||||
|
||||||||||
#if !defined(Q_OS_IOS) && !defined(Q_OS_ANDROID) | ||||||||||
#include "SignalHandler.h" | ||||||||||
#endif | ||||||||||
|
||||||||||
void Platform::disableAppNapViaInfoDict() | ||||||||||
#if defined(Q_OS_MACOS) | ||||||||||
#include <CoreFoundation/CoreFoundation.h> | ||||||||||
#elif defined(Q_OS_WIN) | ||||||||||
#include <qt_windows.h> | ||||||||||
#include <iostream> | ||||||||||
#include <iterator> // std::size | ||||||||||
#include <cwchar> // swprintf | ||||||||||
#if defined(_MSC_VER) | ||||||||||
#include <crtdbg.h> | ||||||||||
#include <stdlib.h> | ||||||||||
#include <cstdio> // _snwprintf_s | ||||||||||
#endif | ||||||||||
#endif | ||||||||||
|
||||||||||
namespace { | ||||||||||
|
||||||||||
#if defined(Q_OS_MACOS) | ||||||||||
void disableAppNapViaInfoDict() | ||||||||||
{ | ||||||||||
CFBundleRef bundle = CFBundleGetMainBundle(); | ||||||||||
if (!bundle) return; | ||||||||||
if (!bundle) { | ||||||||||
return; | ||||||||||
} | ||||||||||
CFMutableDictionaryRef infoDict = const_cast<CFMutableDictionaryRef>(CFBundleGetInfoDictionary(bundle)); | ||||||||||
if (infoDict) { | ||||||||||
CFDictionarySetValue(infoDict, CFSTR("NSAppSleepDisabled"), kCFBooleanTrue); | ||||||||||
} | ||||||||||
} | ||||||||||
#endif // Q_OS_MACOS | ||||||||||
|
||||||||||
// CFBundleGetInfoDictionary returns the dictionary the OS already | ||||||||||
// parsed from Info.plist. Cast it to mutable so we can tweak it. | ||||||||||
CFMutableDictionaryRef infoDict = (CFMutableDictionaryRef) CFBundleGetInfoDictionary(bundle); | ||||||||||
#if defined(Q_OS_WIN) | ||||||||||
|
||||||||||
// Inject the key → true | ||||||||||
if (infoDict) { | ||||||||||
CFDictionarySetValue(infoDict, | ||||||||||
CFSTR("NSAppSleepDisabled"), | ||||||||||
kCFBooleanTrue); | ||||||||||
#if defined(_MSC_VER) | ||||||||||
int __cdecl WindowsCrtReportHook(int reportType, char* message, int* returnValue) | ||||||||||
{ | ||||||||||
if (message) { | ||||||||||
std::cerr << message << std::endl; | ||||||||||
} | ||||||||||
if (reportType == _CRT_ASSERT) { | ||||||||||
if (returnValue) { | ||||||||||
*returnValue = 0; | ||||||||||
} | ||||||||||
return 1; // handled | ||||||||||
} | ||||||||||
return 0; // let CRT continue | ||||||||||
} | ||||||||||
|
||||||||||
void __cdecl WindowsPurecallHandler() | ||||||||||
{ | ||||||||||
(void) OutputDebugStringW(L"QGC: _purecall\n"); | ||||||||||
} | ||||||||||
|
||||||||||
void WindowsInvalidParameterHandler([[maybe_unused]] const wchar_t* expression, | ||||||||||
[[maybe_unused]] const wchar_t* function, | ||||||||||
[[maybe_unused]] const wchar_t* file, | ||||||||||
[[maybe_unused]] unsigned int line, | ||||||||||
[[maybe_unused]] uintptr_t pReserved) | ||||||||||
{ | ||||||||||
|
||||||||||
} | ||||||||||
#endif // _MSC_VER | ||||||||||
|
||||||||||
LPTOP_LEVEL_EXCEPTION_FILTER g_prevUef = nullptr; | ||||||||||
|
||||||||||
LONG WINAPI WindowsUnhandledExceptionFilter(EXCEPTION_POINTERS* ep) | ||||||||||
{ | ||||||||||
const DWORD code = (ep && ep->ExceptionRecord) ? ep->ExceptionRecord->ExceptionCode : 0; | ||||||||||
wchar_t buf[128] = {}; | ||||||||||
#if defined(_MSC_VER) | ||||||||||
(void) _snwprintf_s(buf, _TRUNCATE, L"QGC: unhandled SEH 0x%08lX\n", static_cast<unsigned long>(code)); | ||||||||||
#else | ||||||||||
(void) swprintf(buf, static_cast<int>(std::size(buf)), L"QGC: unhandled SEH 0x%08lX\n", static_cast<unsigned long>(code)); | ||||||||||
#endif | ||||||||||
(void) OutputDebugStringW(buf); | ||||||||||
|
||||||||||
const HANDLE h = GetStdHandle(STD_ERROR_HANDLE); | ||||||||||
if (h && (h != INVALID_HANDLE_VALUE)) { | ||||||||||
DWORD ignored = 0; | ||||||||||
const char narrow[] = "QGC: unhandled SEH\n"; | ||||||||||
(void) WriteFile(h, narrow, (DWORD)sizeof(narrow) - 1, &ignored, nullptr); | ||||||||||
} | ||||||||||
|
||||||||||
HTRamsey marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
HTRamsey marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||
return EXCEPTION_EXECUTE_HANDLER; | ||||||||||
} | ||||||||||
|
||||||||||
void setWindowsErrorModes(bool quietWindowsAsserts) | ||||||||||
{ | ||||||||||
(void) SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX); | ||||||||||
g_prevUef = SetUnhandledExceptionFilter(WindowsUnhandledExceptionFilter); | ||||||||||
|
||||||||||
#if defined(_MSC_VER) | ||||||||||
(void) _set_invalid_parameter_handler(WindowsInvalidParameterHandler); | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The WindowsInvalidParameterHandler function is empty, which may not provide meaningful error handling. Consider adding logging or appropriate error handling logic. Copilot uses AI. Check for mistakes. Positive FeedbackNegative Feedback |
||||||||||
(void) _set_purecall_handler(WindowsPurecallHandler); | ||||||||||
|
||||||||||
if (quietWindowsAsserts) { | ||||||||||
(void) _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG); | ||||||||||
(void) _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_DEBUG); | ||||||||||
(void) _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_DEBUG); | ||||||||||
(void) _CrtSetReportHook2(_CRT_RPTHOOK_INSTALL, WindowsCrtReportHook); | ||||||||||
(void) _set_abort_behavior(0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT); | ||||||||||
(void) _set_error_mode(_OUT_TO_STDERR); | ||||||||||
} | ||||||||||
#else | ||||||||||
Q_UNUSED(quietWindowsAsserts); | ||||||||||
#endif | ||||||||||
} | ||||||||||
#endif // Q_OS_WIN | ||||||||||
|
||||||||||
} // namespace | ||||||||||
|
||||||||||
void Platform::setupPreApp(bool quietWindowsAsserts) | ||||||||||
{ | ||||||||||
#ifdef Q_OS_UNIX | ||||||||||
if (!qEnvironmentVariableIsSet("QT_ASSUME_STDERR_HAS_CONSOLE")) { | ||||||||||
(void) qputenv("QT_ASSUME_STDERR_HAS_CONSOLE", "1"); | ||||||||||
} | ||||||||||
if (!qEnvironmentVariableIsSet("QT_FORCE_STDERR_LOGGING")) { | ||||||||||
(void) qputenv("QT_FORCE_STDERR_LOGGING", "1"); | ||||||||||
} | ||||||||||
#endif | ||||||||||
|
||||||||||
#ifdef Q_OS_WIN | ||||||||||
if (!qEnvironmentVariableIsSet("QT_WIN_DEBUG_CONSOLE")) { | ||||||||||
(void) qputenv("QT_WIN_DEBUG_CONSOLE", "attach"); | ||||||||||
} | ||||||||||
setWindowsErrorModes(quietWindowsAsserts); | ||||||||||
#endif | ||||||||||
|
||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [nitpick] The console control handler is installed unconditionally, but it might be more appropriate to only install it when needed (e.g., when running unit tests or in debug mode). Consider making this conditional based on the application's requirements.
Suggested change
Copilot uses AI. Check for mistakes. Positive FeedbackNegative Feedback |
||||||||||
#ifdef Q_OS_MACOS | ||||||||||
disableAppNapViaInfoDict(); | ||||||||||
#endif | ||||||||||
} | ||||||||||
|
||||||||||
void Platform::setupPostApp() | ||||||||||
{ | ||||||||||
#if !defined(Q_OS_IOS) && !defined(Q_OS_ANDROID) | ||||||||||
SignalHandler* signalHandler = new SignalHandler(QCoreApplication::instance()); | ||||||||||
(void) signalHandler->setupSignalHandlers(); | ||||||||||
#endif | ||||||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,20 @@ | ||
#pragma once | ||
/**************************************************************************** | ||
* | ||
* (c) 2009-2024 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org> | ||
* | ||
* QGroundControl is licensed according to the terms in the file | ||
* COPYING.md in the root of the source code directory. | ||
* | ||
****************************************************************************/ | ||
|
||
#include <QtCore/QtSystemDetection> | ||
#pragma once | ||
|
||
namespace Platform { | ||
#ifdef Q_OS_MAC | ||
/// Prevent Apple's app nap from screwing us over | ||
/// tip: the domain can be cross-checked on the command line with <defaults domains> | ||
void disableAppNapViaInfoDict(); | ||
#endif | ||
} | ||
|
||
// Call before constructing Q(Core)Application. | ||
void setupPreApp(bool quietWindowsAsserts); | ||
|
||
// Call after Q(Core)Application exists and logging is installed. | ||
void setupPostApp(); | ||
|
||
} // namespace Platform |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The buffer size (128) is hardcoded. Consider using a named constant or sizeof(buf) to make the code more maintainable and less error-prone.
Copilot uses AI. Check for mistakes.