Arcane  4.1.12.0
Developer documentation
Loading...
Searching...
No Matches
Misc.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2026 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4// See the top-level COPYRIGHT file for details.
5// SPDX-License-Identifier: Apache-2.0
6//-----------------------------------------------------------------------------
7/*---------------------------------------------------------------------------*/
8/* Misc.cc (C) 2000-2025 */
9/* */
10/* Various functions */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/utils/Iostream.h"
15#include "arcane/utils/Convert.h"
16#include "arcane/utils/StdHeader.h"
17#include "arcane/utils/PlatformUtils.h"
18#include "arcane/utils/FatalErrorException.h"
19#include "arcane/utils/SignalException.h"
20#include "arcane/utils/TimeoutException.h"
21#include "arcane/utils/ArithmeticException.h"
22#include "arcane/utils/IStackTraceService.h"
23#include "arcane/utils/TraceInfo.h"
24#include "arcane/utils/OStringStream.h"
25#include "arcane/utils/IThreadImplementation.h"
26// Not used here but necessary to load symbols in the DLL
27#include "arcane/utils/NullThreadMng.h"
28#include "arcane/utils/CriticalSection.h"
29
30#include <limits.h>
31#include <math.h>
32#ifndef ARCANE_OS_WIN32
33#include <unistd.h>
34#endif
35#include <time.h>
36#include <stdarg.h>
37#include <stdlib.h>
38#ifndef ARCANE_OS_WIN32
39#include <sys/time.h>
40#endif
41
42#define USE_SIGACTION 1
43
44/*---------------------------------------------------------------------------*/
45/*---------------------------------------------------------------------------*/
46
47namespace Arcane
48{
49
50/*---------------------------------------------------------------------------*/
51/*---------------------------------------------------------------------------*/
52
53extern "C" {
54typedef void (*fSignalFunc)(int);
55}
56
57/*---------------------------------------------------------------------------*/
58/*---------------------------------------------------------------------------*/
59
60#ifdef ARCANE_CHECK
61static bool global_arcane_is_check = true;
62#else
63static bool global_arcane_is_check = false;
64#endif
65
66extern "C++" ARCANE_UTILS_EXPORT bool arcaneIsCheck()
67{
68 return global_arcane_is_check;
69}
70
71extern "C++" ARCANE_UTILS_EXPORT void arcaneSetCheck(bool v)
72{
73 global_arcane_is_check = v;
74}
75
76extern "C++" ARCANE_UTILS_EXPORT bool arcaneIsDebug()
77{
78#ifdef ARCANE_DEBUG
79 return true;
80#else
81 return false;
82#endif
83}
84
85/*---------------------------------------------------------------------------*/
86/*---------------------------------------------------------------------------*/
87
88extern "C++" ARCANE_UTILS_EXPORT bool arcaneHasThread()
89{
90 return true;
91}
92
93extern "C++" ARCANE_UTILS_EXPORT void arcaneSetHasThread([[maybe_unused]] bool v)
94{
95 if (!v)
96 std::cout << "WARNING: disabling thread via arcaneSetHasThread() is no longer available.\n";
97}
98
99/*---------------------------------------------------------------------------*/
100/*---------------------------------------------------------------------------*/
101
102extern "C++" ARCANE_UTILS_EXPORT
103Int64
105{
107 if (ti)
108 return ti->currentThread();
109 return 0;
110}
111
112/*---------------------------------------------------------------------------*/
113/*---------------------------------------------------------------------------*/
114
115extern "C++" ARCANE_UTILS_EXPORT void
116arcaneSetPauseOnError(bool v)
117{
119}
120
121extern "C++" ARCANE_UTILS_EXPORT void
122arcaneDebugPause(const char* msg)
123{
125}
126
127/*---------------------------------------------------------------------------*/
128/*---------------------------------------------------------------------------*/
129
130extern "C++" ARCANE_UTILS_EXPORT void
131arcaneNullPointerError(const void* ptr)
132{
133 ARCANE_UNUSED(ptr);
134 cerr << "** FATAL: Trying to use a null pointer.\n";
135 arcaneDebugPause("arcaneNullPointerError");
136 throw FatalErrorException(A_FUNCINFO);
137}
138
139/*---------------------------------------------------------------------------*/
140/*---------------------------------------------------------------------------*/
141
142namespace
143{
144 void _doNoReferenceError(const void* ptr)
145 {
146 cerr << "** FATAL: Null reference.\n";
147 cerr << "** FATAL: Trying to use an item not referenced.\n";
148 cerr << "** FATAL: Item is located at memory address " << ptr << ".\n";
149 arcaneDebugPause("arcaneNoReferenceError");
150 }
151} // namespace
152
153/*---------------------------------------------------------------------------*/
154/*---------------------------------------------------------------------------*/
155
156extern "C++" ARCANE_UTILS_EXPORT void
158{
159 _doNoReferenceError(ptr);
160 throw FatalErrorException(A_FUNCINFO);
161}
162
163/*---------------------------------------------------------------------------*/
164/*---------------------------------------------------------------------------*/
165
166extern "C++" ARCANE_UTILS_EXPORT void
168{
169 _doNoReferenceError(ptr);
170 std::terminate();
171}
172
173/*---------------------------------------------------------------------------*/
174/*---------------------------------------------------------------------------*/
175
176extern "C++" ARCANE_UTILS_EXPORT void
177arcanePrintf(const char* format, ...)
178{
179 // \n is written at the same time to avoid parasitic intermediate writes
180 char buffer[256];
181 va_list ap;
182 va_start(ap, format);
183 vsnprintf(buffer, 256, format, ap);
184 va_end(ap);
185 cerr << buffer << "\n";
186 cout << "*E* " << buffer << "\n";
187}
188
189/*---------------------------------------------------------------------------*/
190/*---------------------------------------------------------------------------*/
191
192extern "C++" ARCANE_UTILS_EXPORT void
193arcaneObsolete(const char* file, const char* func, unsigned long line, const char* text)
194{
195 cerr << file << ':' << func << ':' << line << '\n';
196 cerr << "usage of this function is deprecated";
197 if (text)
198 cerr << ": " << text;
199 cerr << '\n';
200}
201
202/*---------------------------------------------------------------------------*/
203/*---------------------------------------------------------------------------*/
204
206typedef void (*fDoAssert)(const char*, const char*, const char*, size_t);
208typedef bool (*fCheckDebug)(unsigned int);
209
210static fDoAssert g_do_assert_func = 0;
211static fCheckDebug g_check_debug_func = 0;
212
213/*---------------------------------------------------------------------------*/
214/*---------------------------------------------------------------------------*/
215
219ARCANE_UTILS_EXPORT void
220_doAssert(const char* text, const char* file, const char* func, size_t line)
221{
222 if (g_do_assert_func)
223 (*g_do_assert_func)(text, file, func, line);
224 else {
225 std::ostringstream ostr;
226 ostr << text << ':' << file << ':' << func << ':' << line << ": ";
227 throw FatalErrorException("Assert", ostr.str());
228 }
229}
230
231/*---------------------------------------------------------------------------*/
232/*---------------------------------------------------------------------------*/
233
237extern "C++" ARCANE_UTILS_EXPORT bool
238_checkDebug(unsigned int val)
239{
240 if (g_check_debug_func)
241 return (*g_check_debug_func)(val);
242 return false;
243}
244
245/*---------------------------------------------------------------------------*/
246/*---------------------------------------------------------------------------*/
247
248namespace
249{
250 static fSignalFunc g_signal_func = 0;
251}
252
253fSignalFunc
254setSignalFunc(fSignalFunc func)
255{
256 fSignalFunc old = g_signal_func;
257 g_signal_func = func;
258 return old;
259}
260
261/*---------------------------------------------------------------------------*/
262/*---------------------------------------------------------------------------*/
263
264#ifdef ARCANE_OS_LINUX
265#define STD_SIGNAL_TYPE 1
266#endif
267
268#if STD_SIGNAL_TYPE == 1
269#include <sys/signal.h>
270#include <signal.h>
271#include <unistd.h>
272
273//extern "C" void (*sigset (int sig, void (*disp)(int)))(int);
274
275extern "C" void
276_MiscSigFunc(int val)
277{
278 if (g_signal_func)
279 (*g_signal_func)(val);
280}
281
282extern "C" void
283_MiscSigactionFunc(int val, siginfo_t*, void*)
284{
285 if (g_signal_func)
286 (*g_signal_func)(val);
287}
288
289#endif // STD_SIGNAL_TYPE == 1
290
291/*---------------------------------------------------------------------------*/
292/*---------------------------------------------------------------------------*/
293namespace
294{
295#ifndef USE_SIGACTION
296 fSignalFunc default_signal_func_sigsegv = 0;
297 fSignalFunc default_signal_func_sigfpe = 0;
298 fSignalFunc default_signal_func_sigbus = 0;
299 fSignalFunc default_signal_func_sigalrm = 0;
300 fSignalFunc default_signal_func_sigvtalrm = 0;
301#endif
302 bool global_already_in_signal = false;
303} // namespace
304
305extern "C++" ARCANE_UTILS_EXPORT void
306arcaneRedirectSignals(fSignalFunc sig_func)
307{
308 setSignalFunc(sig_func);
309#if STD_SIGNAL_TYPE == 1
310
311#ifdef USE_SIGACTION
312 struct sigaction sa;
313 sa.sa_flags = SA_SIGINFO | SA_NODEFER;
314 sigemptyset(&sa.sa_mask);
315 sa.sa_sigaction = _MiscSigactionFunc;
316
317 sigaction(SIGSEGV, &sa, nullptr); // Segmentation fault.
318 sigaction(SIGFPE, &sa, nullptr); // Floating Exception.
319 sigaction(SIGBUS, &sa, nullptr); // Bus Error.
320 sigaction(SIGALRM, &sa, nullptr); // Signal alarm (ITIMER_REAL)
321 sigaction(SIGVTALRM, &sa, nullptr); // Signal alarm (ITIMER_VIRTUAL)
322#else
323 default_signal_func_sigsegv = sigset(SIGSEGV, _MiscSigFunc); // Segmentation fault.
324 default_signal_func_sigfpe = sigset(SIGFPE, _MiscSigFunc); // Floating Exception.
325 default_signal_func_sigbus = sigset(SIGBUS, _MiscSigFunc); // Bus Error.
326 //default_signal_func_sigsys = sigset(SIGSYS ,_MiscSigFunc); // Bad argument in system call.
327 //default_signal_func_sigpipe = sigset(SIGPIPE,_MiscSigFunc); // Pipe error.
328 default_signal_func_sigalrm = sigset(SIGALRM, _MiscSigFunc); // Signal alarm (ITIMER_REAL)
329 default_signal_func_sigvtalrm = sigset(SIGVTALRM, _MiscSigFunc); // Signal alarm (ITIMER_VIRTUAL)
330#endif // USE_SIGACTION
331#endif // STD_SIGNAL_TYPE == 1
332}
333
334extern "C++" ARCANE_UTILS_EXPORT void
335arcaneCallDefaultSignal(int val)
336{
337#if STD_SIGNAL_TYPE == 1
338
339 //fSignalFunc func = 0;
340 SignalException::eSignalType signal_type = SignalException::ST_Unknown;
341
342 switch (val) {
343 case SIGSEGV:
344 signal_type = SignalException::ST_SegmentationFault;
345 break;
346 case SIGFPE:
347 signal_type = SignalException::ST_FloatingException;
348 break;
349 case SIGBUS:
350 signal_type = SignalException::ST_BusError;
351 break;
352 case SIGALRM:
353 case SIGVTALRM:
354 signal_type = SignalException::ST_Alarm;
355 break;
356 }
357
358 // cerr << "** SIGVAL " << val << ' ' << SIG_DFL
359 // << ' ' << SIG_IGN << " is_in_signal?=" << global_already_in_signal << '\n';
360
361 // If a new signal occurs while already in a handler, or
362 // if it is a memory error signal (SIGBUS or SIGSEGV), we abort.
363 if (global_already_in_signal)
364 ::abort();
365 global_already_in_signal = true;
366
367 arcaneDebugPause("arcaneCallDefaultSignal");
368
369 // To avoid certain problems when recovering the stack
370 // which might cause an exception, we first retrieve the call
371 // stack and pass it to the exception constructor.
372 StackTrace stack_trace;
374 if (stack_service) {
375 stack_trace = stack_service->stackTrace();
376 cerr << " Signal exception Stack: " << stack_trace.toString() << '\n';
377 }
378 else
379 cerr << " No stack trace service\n";
380
381 // If requested, display the call stack via the debugger. This allows for
382 // more information (but it takes longer to execute)
383 bool do_debug_stack = false;
384 if (auto v = Convert::Type<Int32>::tryParseFromEnvironment("ARCANE_DUMP_DEBUGGER_STACK_IN_SIGNAL", true))
385 do_debug_stack = (v.value() != 0);
386 if (do_debug_stack) {
387 std::cerr << "GBDStack pid=" << platform::getProcessId() << " stack=" << platform::getGDBStack() << "\n";
388 }
389 else
390 std::cerr << "SignalCaught: You can dump full stacktrace of the process if environment "
391 "variable ARCANE_DUMP_DEBUGGER_STACK_IN_SIGNAL is set to 1\n";
392
393 if (signal_type == SignalException::ST_Alarm) {
394 global_already_in_signal = false;
395 throw TimeoutException("Arcane.Signal", stack_trace);
396 }
397 else if (signal_type == SignalException::ST_FloatingException) {
398 global_already_in_signal = false;
399 cerr << "** THROW ARITHMETIC EXCEPTION\n";
400 // Re-enable floating exceptions for the next time
402 throw ArithmeticException(A_FUNCINFO, stack_trace);
403 }
404 throw SignalException("Arcane.Signal", stack_trace, signal_type, val);
405#endif
406}
407
408/*---------------------------------------------------------------------------*/
409/*---------------------------------------------------------------------------*/
410
411/*---------------------------------------------------------------------------*/
412/*---------------------------------------------------------------------------*/
413
414#ifdef ARCANE_DEBUG
415extern "C" void
416_PureVirtual()
417{
418 cerr << "** pure virtual method called\n";
419 //pause();
420}
421#endif
422
423class HexaPrint
424{
425 public:
426
427 HexaPrint(Real v)
428 : m_v(v)
429 {}
430
431 public:
432
433 void write(std::ostream& o) const
434 {
435 char* v = (char*)&m_v;
436 o << m_v << " HEXA(";
437 o << (int)v[0] << '-';
438 o << (int)v[1] << '-';
439 o << (int)v[2] << '-';
440 o << (int)v[3] << '-';
441 o << (int)v[4] << '-';
442 o << (int)v[5] << '-';
443 o << (int)v[6] << '-';
444 o << (int)v[7] << ")";
445 }
446 Real m_v;
447};
448
449ARCANE_UTILS_EXPORT std::ostream&
450operator<<(std::ostream& o, const HexaPrint& hp)
451{
452 hp.write(o);
453 return o;
454}
455
456/*---------------------------------------------------------------------------*/
457/*---------------------------------------------------------------------------*/
458
459} // End namespace Arcane
460
461/*---------------------------------------------------------------------------*/
462/*---------------------------------------------------------------------------*/
Exception when an arithmetic error occurs.
Template class for converting a type.
Interface of a function call tracing service.
Exception when a signal occurs.
Information about function call stacks.
IStackTraceService * getStackTraceService()
Service used to obtain the call stack.
IThreadImplementation * getThreadImplementationService()
Service used to manage threads.
void enableFloatingException(bool active)
Enables or disables exceptions during a floating-point calculation. This operation is not supported o...
String getGDBStack()
Retrieves the call stack via gdb.
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
void arcaneNoReferenceErrorCallTerminate(const void *ptr)
Use of an unreferenced object.
Definition Misc.cc:167
void arccoreSetPauseOnError(bool v)
Indicates whether calling arccoreDebugPause() results in a pause.
Int64 arcaneCurrentThread()
Returns the ID of the current thread.
Definition Misc.cc:104
void arccoreDebugPause(const char *msg)
Enters pause mode or throws a fatal error.
bool arcaneIsCheck()
True if running in check mode.
Definition Misc.cc:66
bool arcaneHasThread()
True if arcane is compiled with thread support AND they are active.
Definition Misc.cc:88
void arcaneSetHasThread(bool v)
Activates or deactivates thread support.
Definition Misc.cc:93
void arcaneNullPointerError()
Signals the use of a null pointer.
void arcanePrintf(const char *,...)
Encapsulation of the C printf function.
Definition Misc.cc:177
void(* fDoAssert)(const char *, const char *, const char *, size_t)
Function called when an assertion fails.
Definition Misc.cc:206
bool arcaneIsDebug()
True if the ARCANE_DEBUG macro is defined.
Definition Misc.cc:76
void arcaneSetCheck(bool v)
Activates or deactivates verification mode.
Definition Misc.cc:71
bool(* fCheckDebug)(unsigned int)
Function called to indicate whether debug information should be displayed.
Definition Misc.cc:208
void arcaneNoReferenceError(const void *ptr)
Use of an unreferenced object.
Definition Misc.cc:157
bool _checkDebug(unsigned int val)
Definition Misc.cc:238
double Real
Type representing a real number.
void _doAssert(const char *text, const char *file, const char *func, size_t line)
Definition Misc.cc:220
void arcaneDebugPause(const char *msg)
Enters pause mode or throws a fatal error.
Definition Misc.cc:122