2023-08-16 00:20:26 +10:00
|
|
|
/* SPDX-FileCopyrightText: 2023 Blender Authors
|
2023-05-31 16:19:06 +02:00
|
|
|
*
|
|
|
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
2016-02-28 05:10:00 +11:00
|
|
|
|
2019-02-18 08:08:12 +11:00
|
|
|
/** \file
|
|
|
|
|
* \ingroup creator
|
2016-02-28 05:10:00 +11:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#ifndef WITH_PYTHON_MODULE
|
|
|
|
|
|
2025-04-04 18:38:53 +02:00
|
|
|
# include <cerrno>
|
|
|
|
|
# include <cstdlib>
|
|
|
|
|
|
2016-02-28 05:10:00 +11:00
|
|
|
# if defined(__linux__) && defined(__GNUC__)
|
2023-08-02 15:34:45 +02:00
|
|
|
# ifndef _GNU_SOURCE
|
|
|
|
|
# define _GNU_SOURCE
|
|
|
|
|
# endif
|
2023-08-03 08:57:59 +10:00
|
|
|
# include <cfenv>
|
2016-02-28 05:10:00 +11:00
|
|
|
# endif
|
|
|
|
|
|
|
|
|
|
# if (defined(__APPLE__) && (defined(__i386__) || defined(__x86_64__)))
|
|
|
|
|
# define OSX_SSE_FPE
|
|
|
|
|
# include <xmmintrin.h>
|
2019-04-17 06:17:24 +02:00
|
|
|
# endif
|
|
|
|
|
|
2016-02-28 05:10:00 +11:00
|
|
|
# ifdef WIN32
|
|
|
|
|
# include <float.h>
|
2020-03-19 09:33:03 +01:00
|
|
|
# include <windows.h>
|
2016-02-28 05:10:00 +11:00
|
|
|
|
|
|
|
|
# include "BLI_winstuff.h"
|
2025-04-04 18:38:53 +02:00
|
|
|
|
|
|
|
|
# include "GPU_platform.hh"
|
2016-02-28 05:10:00 +11:00
|
|
|
# endif
|
2025-04-04 18:38:53 +02:00
|
|
|
|
2016-02-28 05:10:00 +11:00
|
|
|
# include "BLI_fileops.h"
|
2024-09-26 21:13:39 +10:00
|
|
|
# include "BLI_path_utils.hh"
|
2020-03-19 09:33:03 +01:00
|
|
|
# include "BLI_string.h"
|
2016-02-28 05:10:00 +11:00
|
|
|
# include "BLI_system.h"
|
|
|
|
|
# include BLI_SYSTEM_PID_H
|
|
|
|
|
|
2025-04-04 18:38:53 +02:00
|
|
|
# include "BKE_appdir.hh" /* #BKE_tempdir_session_purge. */
|
|
|
|
|
# include "BKE_blender.hh"
|
2016-04-24 22:42:41 +10:00
|
|
|
# include "BKE_blender_version.h"
|
2024-02-10 18:25:14 +01:00
|
|
|
# include "BKE_global.hh"
|
2023-12-01 19:43:16 +01:00
|
|
|
# include "BKE_main.hh"
|
2024-02-10 18:34:29 +01:00
|
|
|
# include "BKE_report.hh"
|
2024-02-15 16:42:35 +01:00
|
|
|
# include "BKE_wm_runtime.hh"
|
2016-02-28 05:10:00 +11:00
|
|
|
|
2023-08-03 08:57:59 +10:00
|
|
|
# include <csignal>
|
2016-02-28 05:10:00 +11:00
|
|
|
|
2020-08-06 15:34:55 +10:00
|
|
|
# ifdef WITH_PYTHON
|
2024-09-24 17:07:49 +02:00
|
|
|
# include "BPY_extern_python.hh" /* #BPY_python_backtrace. */
|
2020-08-06 15:34:55 +10:00
|
|
|
# endif
|
|
|
|
|
|
2024-03-19 13:57:00 +11:00
|
|
|
# include "creator_intern.h" /* Own include. */
|
2016-02-28 05:10:00 +11:00
|
|
|
|
|
|
|
|
# if defined(__linux__) || defined(_WIN32) || defined(OSX_SSE_FPE)
|
2024-03-19 13:57:00 +11:00
|
|
|
/**
|
|
|
|
|
* Set breakpoints here when running in debug mode, useful to catch floating point errors.
|
|
|
|
|
*/
|
2023-08-02 15:34:45 +02:00
|
|
|
static void sig_handle_fpe(int /*sig*/)
|
2016-02-28 05:10:00 +11:00
|
|
|
{
|
|
|
|
|
fprintf(stderr, "debug: SIGFPE trapped\n");
|
|
|
|
|
}
|
|
|
|
|
# endif
|
|
|
|
|
|
2021-09-27 21:01:48 +10:00
|
|
|
/* Handling `Ctrl-C` event in the console. */
|
2016-02-28 05:10:00 +11:00
|
|
|
static void sig_handle_blender_esc(int sig)
|
|
|
|
|
{
|
2024-03-19 13:57:00 +11:00
|
|
|
/* Forces render loop to read queue, not sure if its needed. */
|
|
|
|
|
G.is_break = true;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-02-28 05:10:00 +11:00
|
|
|
if (sig == 2) {
|
2022-08-26 12:51:46 +10:00
|
|
|
static int count = 0;
|
2016-02-28 05:10:00 +11:00
|
|
|
if (count) {
|
|
|
|
|
printf("\nBlender killed\n");
|
|
|
|
|
exit(2);
|
|
|
|
|
}
|
|
|
|
|
printf("\nSent an internal break event. Press ^C again to kill Blender\n");
|
|
|
|
|
count++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-04 18:38:53 +02:00
|
|
|
static void crashlog_file_generate(const char *filepath, const void *os_info)
|
2016-02-28 05:10:00 +11:00
|
|
|
{
|
2023-08-02 15:34:45 +02:00
|
|
|
/* Might be called after WM/Main exit, so needs to be careful about nullptr-checking before
|
2020-01-25 20:09:20 +11:00
|
|
|
* de-referencing. */
|
2020-01-15 18:08:34 +01:00
|
|
|
|
2023-08-02 15:34:45 +02:00
|
|
|
wmWindowManager *wm = G_MAIN ? static_cast<wmWindowManager *>(G_MAIN->wm.first) : nullptr;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-02-28 05:10:00 +11:00
|
|
|
FILE *fp;
|
|
|
|
|
char header[512];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-05-03 14:13:27 +10:00
|
|
|
printf("Writing: %s\n", filepath);
|
2016-02-28 05:10:00 +11:00
|
|
|
fflush(stdout);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-02-28 05:10:00 +11:00
|
|
|
# ifndef BUILD_DATE
|
2023-05-09 12:50:37 +10:00
|
|
|
SNPRINTF(header, "# " BLEND_VERSION_FMT ", Unknown revision\n", BLEND_VERSION_ARG);
|
2016-02-28 05:10:00 +11:00
|
|
|
# else
|
2023-05-13 17:34:21 +10:00
|
|
|
SNPRINTF(header,
|
|
|
|
|
"# " BLEND_VERSION_FMT ", Commit date: %s %s, Hash %s\n",
|
|
|
|
|
BLEND_VERSION_ARG,
|
|
|
|
|
build_commit_date,
|
|
|
|
|
build_commit_time,
|
|
|
|
|
build_hash);
|
2016-02-28 05:10:00 +11:00
|
|
|
# endif
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2024-03-19 13:57:00 +11:00
|
|
|
/* Open the crash log. */
|
2016-02-28 05:10:00 +11:00
|
|
|
errno = 0;
|
2023-05-03 14:13:27 +10:00
|
|
|
fp = BLI_fopen(filepath, "wb");
|
2023-08-02 15:34:45 +02:00
|
|
|
if (fp == nullptr) {
|
2016-02-28 05:10:00 +11:00
|
|
|
fprintf(stderr,
|
|
|
|
|
"Unable to save '%s': %s\n",
|
2023-05-03 14:13:27 +10:00
|
|
|
filepath,
|
2016-02-28 05:10:00 +11:00
|
|
|
errno ? strerror(errno) : "Unknown error opening file");
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
if (wm) {
|
2024-02-15 16:42:35 +01:00
|
|
|
BKE_report_write_file_fp(fp, &wm->runtime->reports, header);
|
2016-02-28 05:10:00 +11:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2024-11-08 23:17:36 +01:00
|
|
|
fputs("\n# backtrace\n", fp);
|
|
|
|
|
BLI_system_backtrace_with_os_info(fp, os_info);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-08-06 15:34:55 +10:00
|
|
|
# ifdef WITH_PYTHON
|
|
|
|
|
/* Generate python back-trace if Python is currently active. */
|
|
|
|
|
BPY_python_backtrace(fp);
|
|
|
|
|
# endif
|
|
|
|
|
|
2016-02-28 05:10:00 +11:00
|
|
|
fclose(fp);
|
|
|
|
|
}
|
2025-04-04 18:38:53 +02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2025-04-04 18:38:53 +02:00
|
|
|
static void sig_cleanup_and_terminate(int signum)
|
|
|
|
|
{
|
2024-03-21 10:01:43 +11:00
|
|
|
/* Delete content of temp directory. */
|
2016-02-28 05:10:00 +11:00
|
|
|
BKE_tempdir_session_purge();
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2024-03-19 13:57:00 +11:00
|
|
|
/* Really crash. */
|
2016-02-28 05:10:00 +11:00
|
|
|
signal(signum, SIG_DFL);
|
|
|
|
|
# ifndef WIN32
|
|
|
|
|
kill(getpid(), signum);
|
|
|
|
|
# else
|
|
|
|
|
TerminateProcess(GetCurrentProcess(), signum);
|
|
|
|
|
# endif
|
|
|
|
|
}
|
|
|
|
|
|
2024-11-08 23:17:36 +01:00
|
|
|
static void sig_handle_crash_fn(int signum)
|
|
|
|
|
{
|
2025-04-04 18:38:53 +02:00
|
|
|
char filepath_crashlog[FILE_MAX];
|
|
|
|
|
BKE_blender_globals_crash_path_get(filepath_crashlog);
|
|
|
|
|
crashlog_file_generate(filepath_crashlog, nullptr);
|
|
|
|
|
sig_cleanup_and_terminate(signum);
|
2024-11-08 23:17:36 +01:00
|
|
|
}
|
|
|
|
|
|
2016-02-28 05:10:00 +11:00
|
|
|
# ifdef WIN32
|
2020-05-01 07:37:48 -06:00
|
|
|
extern LONG WINAPI windows_exception_handler(EXCEPTION_POINTERS *ExceptionInfo)
|
2016-02-28 05:10:00 +11:00
|
|
|
{
|
2020-05-01 07:37:48 -06:00
|
|
|
/* If this is a stack overflow then we can't walk the stack, so just try to show
|
2024-03-19 13:57:00 +11:00
|
|
|
* where the error happened. */
|
2020-05-01 07:37:48 -06:00
|
|
|
if (ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_STACK_OVERFLOW) {
|
2020-05-03 13:42:49 +10:00
|
|
|
HMODULE mod;
|
|
|
|
|
CHAR modulename[MAX_PATH];
|
|
|
|
|
LPVOID address = ExceptionInfo->ExceptionRecord->ExceptionAddress;
|
|
|
|
|
fprintf(stderr, "Error : EXCEPTION_STACK_OVERFLOW\n");
|
|
|
|
|
fprintf(stderr, "Address : 0x%p\n", address);
|
2023-08-02 15:34:45 +02:00
|
|
|
if (GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, LPCSTR(address), &mod)) {
|
2020-05-03 13:42:49 +10:00
|
|
|
if (GetModuleFileName(mod, modulename, MAX_PATH)) {
|
|
|
|
|
fprintf(stderr, "Module : %s\n", modulename);
|
2017-11-07 07:57:59 -07:00
|
|
|
}
|
2020-05-03 13:42:49 +10:00
|
|
|
}
|
2020-05-01 07:37:48 -06:00
|
|
|
}
|
|
|
|
|
else {
|
2025-07-22 09:04:14 +02:00
|
|
|
char filepath_crashlog[FILE_MAX];
|
|
|
|
|
BLI_windows_exception_print_message(ExceptionInfo);
|
|
|
|
|
BKE_blender_globals_crash_path_get(filepath_crashlog);
|
|
|
|
|
crashlog_file_generate(filepath_crashlog, ExceptionInfo);
|
|
|
|
|
|
|
|
|
|
/* Disable popup in background mode to avoid blocking automation.
|
|
|
|
|
* (e.g., when used by a render farm; see #142314). */
|
|
|
|
|
if (!G.background) {
|
|
|
|
|
std::string version;
|
2025-04-04 18:38:53 +02:00
|
|
|
# ifndef BUILD_DATE
|
2025-07-22 09:04:14 +02:00
|
|
|
const char *build_hash = G_MAIN ? G_MAIN->build_hash : "unknown";
|
|
|
|
|
version = std::string(BKE_blender_version_string()) + ", hash: `" + build_hash + "`";
|
2025-04-04 18:38:53 +02:00
|
|
|
# else
|
2025-07-22 09:04:14 +02:00
|
|
|
version = std::string(BKE_blender_version_string()) + ", Commit date: " + build_commit_date +
|
|
|
|
|
" " + build_commit_time + ", hash: `" + build_hash + "`";
|
2025-04-04 18:38:53 +02:00
|
|
|
# endif
|
|
|
|
|
|
2025-07-22 09:04:14 +02:00
|
|
|
BLI_windows_exception_show_dialog(
|
|
|
|
|
filepath_crashlog, G.filepath_last_blend, GPU_platform_gpu_name(), version.c_str());
|
|
|
|
|
}
|
2025-04-04 18:38:53 +02:00
|
|
|
sig_cleanup_and_terminate(SIGSEGV);
|
2016-02-28 05:10:00 +11:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-02-28 05:10:00 +11:00
|
|
|
return EXCEPTION_EXECUTE_HANDLER;
|
|
|
|
|
}
|
|
|
|
|
# endif
|
|
|
|
|
|
2023-08-02 15:34:45 +02:00
|
|
|
static void sig_handle_abort(int /*signum*/)
|
2016-02-28 05:10:00 +11:00
|
|
|
{
|
2024-03-21 10:01:43 +11:00
|
|
|
/* Delete content of temp directory. */
|
2016-02-28 05:10:00 +11:00
|
|
|
BKE_tempdir_session_purge();
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-03 08:57:59 +10:00
|
|
|
void main_signal_setup()
|
2016-02-28 05:10:00 +11:00
|
|
|
{
|
|
|
|
|
if (app_state.signal.use_crash_handler) {
|
|
|
|
|
# ifdef WIN32
|
|
|
|
|
SetUnhandledExceptionFilter(windows_exception_handler);
|
|
|
|
|
# else
|
2024-03-19 13:57:00 +11:00
|
|
|
/* After parsing arguments. */
|
2024-11-08 23:17:36 +01:00
|
|
|
signal(SIGSEGV, sig_handle_crash_fn);
|
2016-02-28 05:10:00 +11:00
|
|
|
# endif
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-09-29 11:42:02 -07:00
|
|
|
# ifdef WIN32
|
|
|
|
|
/* Prevent any error mode dialogs from hanging the application. */
|
|
|
|
|
SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOALIGNMENTFAULTEXCEPT | SEM_NOGPFAULTERRORBOX |
|
|
|
|
|
SEM_NOOPENFILEERRORBOX);
|
|
|
|
|
# endif
|
|
|
|
|
|
2016-02-28 05:10:00 +11:00
|
|
|
if (app_state.signal.use_abort_handler) {
|
|
|
|
|
signal(SIGABRT, sig_handle_abort);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-03 08:57:59 +10:00
|
|
|
void main_signal_setup_background()
|
2016-02-28 05:10:00 +11:00
|
|
|
{
|
2019-07-31 14:25:09 +02:00
|
|
|
/* for all platforms, even windows has it! */
|
2016-02-28 05:10:00 +11:00
|
|
|
BLI_assert(G.background);
|
|
|
|
|
|
2021-10-18 11:16:24 +11:00
|
|
|
/* Support pressing `Ctrl-C` to close Blender in background-mode.
|
|
|
|
|
* Useful to be able to cancel a render operation. */
|
|
|
|
|
signal(SIGINT, sig_handle_blender_esc);
|
2016-02-28 05:10:00 +11:00
|
|
|
}
|
|
|
|
|
|
2023-08-03 08:57:59 +10:00
|
|
|
void main_signal_setup_fpe()
|
2016-02-28 05:10:00 +11:00
|
|
|
{
|
|
|
|
|
# if defined(__linux__) || defined(_WIN32) || defined(OSX_SSE_FPE)
|
2024-03-19 13:57:00 +11:00
|
|
|
/* Zealous but makes float issues a heck of a lot easier to find!
|
|
|
|
|
* Set breakpoints on #sig_handle_fpe. */
|
2016-02-28 05:10:00 +11:00
|
|
|
signal(SIGFPE, sig_handle_fpe);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-08-18 08:04:56 +10:00
|
|
|
# if defined(__linux__) && defined(__GNUC__) && defined(HAVE_FEENABLEEXCEPT)
|
2016-02-28 05:10:00 +11:00
|
|
|
feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW);
|
|
|
|
|
# endif /* defined(__linux__) && defined(__GNUC__) */
|
|
|
|
|
# if defined(OSX_SSE_FPE)
|
|
|
|
|
/* OSX uses SSE for floating point by default, so here
|
2024-03-19 13:57:00 +11:00
|
|
|
* use SSE instructions to throw floating point exceptions. */
|
2016-02-28 05:10:00 +11:00
|
|
|
_MM_SET_EXCEPTION_MASK(_MM_MASK_MASK &
|
|
|
|
|
~(_MM_MASK_OVERFLOW | _MM_MASK_INVALID | _MM_MASK_DIV_ZERO));
|
|
|
|
|
# endif /* OSX_SSE_FPE */
|
|
|
|
|
# if defined(_WIN32) && defined(_MSC_VER)
|
2024-03-19 13:57:00 +11:00
|
|
|
/* Enables all floating-point exceptions. */
|
2023-08-02 15:34:45 +02:00
|
|
|
_controlfp_s(nullptr, 0, _MCW_EM);
|
2024-03-19 13:57:00 +11:00
|
|
|
/* Hide the ones we don't care about. */
|
2023-08-02 15:34:45 +02:00
|
|
|
_controlfp_s(nullptr, _EM_DENORMAL | _EM_UNDERFLOW | _EM_INEXACT, _MCW_EM);
|
2016-02-28 05:10:00 +11:00
|
|
|
# endif /* _WIN32 && _MSC_VER */
|
|
|
|
|
# endif
|
|
|
|
|
}
|
|
|
|
|
|
2018-03-19 14:17:59 +01:00
|
|
|
#endif /* WITH_PYTHON_MODULE */
|