Blender V4.3
creator_signals.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#ifndef WITH_PYTHON_MODULE
10
11# if defined(__linux__) && defined(__GNUC__)
12# ifndef _GNU_SOURCE
13# define _GNU_SOURCE
14# endif
15# include <cfenv>
16# endif
17
18# if (defined(__APPLE__) && (defined(__i386__) || defined(__x86_64__)))
19# define OSX_SSE_FPE
20# include <xmmintrin.h>
21# endif
22
23# ifdef WIN32
24# include <float.h>
25# include <windows.h>
26# endif
27
28# include <cerrno>
29# include <cstdlib>
30# include <cstring>
31
32# ifdef WIN32
33# include "BLI_winstuff.h"
34# endif
35# include "BLI_fileops.h"
36# include "BLI_path_utils.hh"
37# include "BLI_string.h"
38# include "BLI_system.h"
39# include "BLI_utildefines.h"
40# include BLI_SYSTEM_PID_H
41
42# include "BKE_appdir.hh" /* #BKE_tempdir_base. */
43# include "BKE_blender_version.h"
44# include "BKE_global.hh"
45# include "BKE_main.hh"
46# include "BKE_report.hh"
47# include "BKE_wm_runtime.hh"
48
49# include <csignal>
50
51# ifdef WITH_PYTHON
52# include "BPY_extern_python.hh" /* #BPY_python_backtrace. */
53# endif
54
55# include "creator_intern.h" /* Own include. */
56
57# if defined(__linux__) || defined(_WIN32) || defined(OSX_SSE_FPE)
61static void sig_handle_fpe(int /*sig*/)
62{
63 fprintf(stderr, "debug: SIGFPE trapped\n");
64}
65# endif
66
67/* Handling `Ctrl-C` event in the console. */
68static void sig_handle_blender_esc(int sig)
69{
70 /* Forces render loop to read queue, not sure if its needed. */
71 G.is_break = true;
72
73 if (sig == 2) {
74 static int count = 0;
75 if (count) {
76 printf("\nBlender killed\n");
77 exit(2);
78 }
79 printf("\nSent an internal break event. Press ^C again to kill Blender\n");
80 count++;
81 }
82}
83
84static void sig_handle_crash_backtrace(FILE *fp)
85{
86 fputs("\n# backtrace\n", fp);
88}
89
90static void sig_handle_crash(int signum)
91{
92 /* Might be called after WM/Main exit, so needs to be careful about nullptr-checking before
93 * de-referencing. */
94
95 wmWindowManager *wm = G_MAIN ? static_cast<wmWindowManager *>(G_MAIN->wm.first) : nullptr;
96
97 FILE *fp;
98 char header[512];
99
100 char filepath[FILE_MAX];
101
102 if (!(G_MAIN && G_MAIN->filepath[0])) {
103 BLI_path_join(filepath, sizeof(filepath), BKE_tempdir_base(), "blender.crash.txt");
104 }
105 else {
107 filepath, sizeof(filepath), BKE_tempdir_base(), BLI_path_basename(G_MAIN->filepath));
108 BLI_path_extension_replace(filepath, sizeof(filepath), ".crash.txt");
109 }
110
111 printf("Writing: %s\n", filepath);
112 fflush(stdout);
113
114# ifndef BUILD_DATE
115 SNPRINTF(header, "# " BLEND_VERSION_FMT ", Unknown revision\n", BLEND_VERSION_ARG);
116# else
117 SNPRINTF(header,
118 "# " BLEND_VERSION_FMT ", Commit date: %s %s, Hash %s\n",
122 build_hash);
123# endif
124
125 /* Open the crash log. */
126 errno = 0;
127 fp = BLI_fopen(filepath, "wb");
128 if (fp == nullptr) {
129 fprintf(stderr,
130 "Unable to save '%s': %s\n",
131 filepath,
132 errno ? strerror(errno) : "Unknown error opening file");
133 }
134 else {
135 if (wm) {
136 BKE_report_write_file_fp(fp, &wm->runtime->reports, header);
137 }
138
140
141# ifdef WITH_PYTHON
142 /* Generate python back-trace if Python is currently active. */
144# endif
145
146 fclose(fp);
147 }
148
149 /* Delete content of temp directory. */
151
152 /* Really crash. */
153 signal(signum, SIG_DFL);
154# ifndef WIN32
155 kill(getpid(), signum);
156# else
157 TerminateProcess(GetCurrentProcess(), signum);
158# endif
159}
160
161# ifdef WIN32
162extern LONG WINAPI windows_exception_handler(EXCEPTION_POINTERS *ExceptionInfo)
163{
164 /* If this is a stack overflow then we can't walk the stack, so just try to show
165 * where the error happened. */
166 if (ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_STACK_OVERFLOW) {
167 HMODULE mod;
168 CHAR modulename[MAX_PATH];
169 LPVOID address = ExceptionInfo->ExceptionRecord->ExceptionAddress;
170 fprintf(stderr, "Error : EXCEPTION_STACK_OVERFLOW\n");
171 fprintf(stderr, "Address : 0x%p\n", address);
172 if (GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, LPCSTR(address), &mod)) {
173 if (GetModuleFileName(mod, modulename, MAX_PATH)) {
174 fprintf(stderr, "Module : %s\n", modulename);
175 }
176 }
177 }
178 else {
179 BLI_windows_handle_exception(ExceptionInfo);
180 sig_handle_crash(SIGSEGV);
181 }
182
183 return EXCEPTION_EXECUTE_HANDLER;
184}
185# endif
186
187static void sig_handle_abort(int /*signum*/)
188{
189 /* Delete content of temp directory. */
191}
192
194{
196# ifdef WIN32
197 SetUnhandledExceptionFilter(windows_exception_handler);
198# else
199 /* After parsing arguments. */
200 signal(SIGSEGV, sig_handle_crash);
201# endif
202 }
203
204# ifdef WIN32
205 /* Prevent any error mode dialogs from hanging the application. */
206 SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOALIGNMENTFAULTEXCEPT | SEM_NOGPFAULTERRORBOX |
207 SEM_NOOPENFILEERRORBOX);
208# endif
209
211 signal(SIGABRT, sig_handle_abort);
212 }
213}
214
216{
217 /* for all platforms, even windows has it! */
218 BLI_assert(G.background);
219
220 /* Support pressing `Ctrl-C` to close Blender in background-mode.
221 * Useful to be able to cancel a render operation. */
222 signal(SIGINT, sig_handle_blender_esc);
223}
224
226{
227# if defined(__linux__) || defined(_WIN32) || defined(OSX_SSE_FPE)
228 /* Zealous but makes float issues a heck of a lot easier to find!
229 * Set breakpoints on #sig_handle_fpe. */
230 signal(SIGFPE, sig_handle_fpe);
231
232# if defined(__linux__) && defined(__GNUC__) && defined(HAVE_FEENABLEEXCEPT)
233 feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW);
234# endif /* defined(__linux__) && defined(__GNUC__) */
235# if defined(OSX_SSE_FPE)
236 /* OSX uses SSE for floating point by default, so here
237 * use SSE instructions to throw floating point exceptions. */
238 _MM_SET_EXCEPTION_MASK(_MM_MASK_MASK &
239 ~(_MM_MASK_OVERFLOW | _MM_MASK_INVALID | _MM_MASK_DIV_ZERO));
240# endif /* OSX_SSE_FPE */
241# if defined(_WIN32) && defined(_MSC_VER)
242 /* Enables all floating-point exceptions. */
243 _controlfp_s(nullptr, 0, _MCW_EM);
244 /* Hide the ones we don't care about. */
245 _controlfp_s(nullptr, _EM_DENORMAL | _EM_UNDERFLOW | _EM_INEXACT, _MCW_EM);
246# endif /* _WIN32 && _MSC_VER */
247# endif
248}
249
250#endif /* WITH_PYTHON_MODULE */
const char * BKE_tempdir_base() ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL
Definition appdir.cc:1211
void BKE_tempdir_session_purge()
Definition appdir.cc:1216
#define G_MAIN
bool BKE_report_write_file_fp(FILE *fp, ReportList *reports, const char *header)
Definition report.cc:356
#define BLI_assert(a)
Definition BLI_assert.h:50
File and directory operations.
FILE * BLI_fopen(const char *filepath, const char *mode) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
void void void const char * BLI_path_basename(const char *path) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT
#define FILE_MAX
bool BLI_path_extension_replace(char *path, size_t path_maxncpy, const char *ext) ATTR_NONNULL(1
#define BLI_path_join(...)
#define SNPRINTF(dst, format,...)
Definition BLI_string.h:597
void BLI_system_backtrace(FILE *fp)
Definition system.c:63
Compatibility-like things for windows.
void BPY_python_backtrace(FILE *fp)
char build_commit_date[]
Definition bpy_app.cc:66
char build_commit_time[]
Definition bpy_app.cc:67
ApplicationState app_state
Definition creator.cc:116
#define printf
#define BLEND_VERSION_ARG
#define BLEND_VERSION_FMT
static void sig_handle_abort(int)
void main_signal_setup_background()
void main_signal_setup_fpe()
static void sig_handle_crash(int signum)
static void sig_handle_blender_esc(int sig)
void main_signal_setup()
static void sig_handle_crash_backtrace(FILE *fp)
char build_hash[16]
int count
#define G(x, y, z)
struct ApplicationState::@1407 signal
WindowManagerRuntimeHandle * runtime
void BLI_windows_handle_exception(EXCEPTION_POINTERS *exception)
ccl_device_inline int mod(int x, int m)
Definition util/math.h:520