Arcane  v4.1.2.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
Misc.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2025 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/* Diverses fonctions */
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// Pas utilise ici mais necessaire pour charger les symbols dans la 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"
54{
55 typedef void (*fSignalFunc)(int);
56}
57
58/*---------------------------------------------------------------------------*/
59/*---------------------------------------------------------------------------*/
60
61#ifdef ARCANE_CHECK
62static bool global_arcane_is_check = true;
63#else
64static bool global_arcane_is_check = false;
65#endif
66
67extern "C++" ARCANE_UTILS_EXPORT
69{
70 return global_arcane_is_check;
71}
72
73extern "C++" ARCANE_UTILS_EXPORT
74void arcaneSetCheck(bool v)
75{
76 global_arcane_is_check = v;
77}
78
79extern "C++" ARCANE_UTILS_EXPORT
81{
82#ifdef ARCANE_DEBUG
83 return true;
84#else
85 return false;
86#endif
87}
88
89/*---------------------------------------------------------------------------*/
90/*---------------------------------------------------------------------------*/
91
92extern "C++" ARCANE_UTILS_EXPORT
94{
95 return true;
96}
97
98extern "C++" ARCANE_UTILS_EXPORT
99void arcaneSetHasThread([[maybe_unused]] bool v)
100{
101 if (!v)
102 std::cout << "WARNING: disabling thread via arcaneSetHasThread() is no longer available.\n";
103}
104
105/*---------------------------------------------------------------------------*/
106/*---------------------------------------------------------------------------*/
107
108extern "C++" ARCANE_UTILS_EXPORT
110{
112 if (ti)
113 return ti->currentThread();
114 return 0;
115}
116
117/*---------------------------------------------------------------------------*/
118/*---------------------------------------------------------------------------*/
119
120extern "C++" ARCANE_UTILS_EXPORT void
121arcaneSetPauseOnError(bool v)
122{
124}
125
126extern "C++" ARCANE_UTILS_EXPORT void
127arcaneDebugPause(const char* msg)
128{
130}
131
132/*---------------------------------------------------------------------------*/
133/*---------------------------------------------------------------------------*/
134
135extern "C++" ARCANE_UTILS_EXPORT void
136arcaneNullPointerError(const void* ptr)
137{
138 ARCANE_UNUSED(ptr);
139 cerr << "** FATAL: Trying to use a null pointer.\n";
140 arcaneDebugPause("arcaneNullPointerError");
141 throw FatalErrorException(A_FUNCINFO);
142}
143
144/*---------------------------------------------------------------------------*/
145/*---------------------------------------------------------------------------*/
146
147namespace
148{
149void _doNoReferenceError(const void* ptr)
150{
151 cerr << "** FATAL: Null reference.\n";
152 cerr << "** FATAL: Trying to use an item not referenced.\n";
153 cerr << "** FATAL: Item is located at memory address " << ptr << ".\n";
154 arcaneDebugPause("arcaneNoReferenceError");
155}
156}
157
158/*---------------------------------------------------------------------------*/
159/*---------------------------------------------------------------------------*/
160
161extern "C++" ARCANE_UTILS_EXPORT void
163{
164 _doNoReferenceError(ptr);
165 throw FatalErrorException(A_FUNCINFO);
166}
167
168/*---------------------------------------------------------------------------*/
169/*---------------------------------------------------------------------------*/
170
171extern "C++" ARCANE_UTILS_EXPORT void
173{
174 _doNoReferenceError(ptr);
175 std::terminate();
176}
177
178/*---------------------------------------------------------------------------*/
179/*---------------------------------------------------------------------------*/
180
181extern "C++" ARCANE_UTILS_EXPORT void
182arcanePrintf(const char* format,...)
183{
184 // \n écrit en meme temps pour éviter des écritures intermédiares parasites
185 char buffer[256];
186 va_list ap;
187 va_start(ap,format);
188 vsnprintf(buffer,256,format,ap);
189 va_end(ap);
190 cerr << buffer << "\n";
191 cout << "*E* " << buffer << "\n";
192}
193
194/*---------------------------------------------------------------------------*/
195/*---------------------------------------------------------------------------*/
196
197extern "C++" ARCANE_UTILS_EXPORT void
198arcaneObsolete(const char* file,const char* func,unsigned long line,const char* text)
199{
200 cerr << file << ':' << func << ':' << line << '\n';
201 cerr << "usage of this function is deprecated";
202 if (text)
203 cerr << ": " << text;
204 cerr << '\n';
205}
206
207
208/*---------------------------------------------------------------------------*/
209/*---------------------------------------------------------------------------*/
210
212typedef void (*fDoAssert)(const char*,const char*,const char*,size_t);
214typedef bool (*fCheckDebug)(unsigned int);
215
216static fDoAssert g_do_assert_func = 0;
217static fCheckDebug g_check_debug_func = 0;
218
219/*---------------------------------------------------------------------------*/
220/*---------------------------------------------------------------------------*/
224ARCANE_UTILS_EXPORT void
225_doAssert(const char* text,const char* file,const char* func,size_t line)
226{
227 if (g_do_assert_func)
228 (*g_do_assert_func)(text,file,func,line);
229 else{
230 std::ostringstream ostr;
231 ostr << text << ':' << file << ':' << func << ':' << line << ": ";
232 throw FatalErrorException("Assert",ostr.str());
233 }
234}
235
236/*---------------------------------------------------------------------------*/
237/*---------------------------------------------------------------------------*/
241extern "C++" ARCANE_UTILS_EXPORT bool
242_checkDebug(unsigned int val)
243{
244 if (g_check_debug_func)
245 return (*g_check_debug_func)(val);
246 return false;
247}
248
249/*---------------------------------------------------------------------------*/
250/*---------------------------------------------------------------------------*/
251
252namespace
253{
254static fSignalFunc g_signal_func = 0;
255}
256
257fSignalFunc
258setSignalFunc(fSignalFunc func)
259{
260 fSignalFunc old = g_signal_func;
261 g_signal_func = func;
262 return old;
263}
264
265/*---------------------------------------------------------------------------*/
266/*---------------------------------------------------------------------------*/
267
268#ifdef ARCANE_OS_LINUX
269#define STD_SIGNAL_TYPE 1
270#endif
271
272#if STD_SIGNAL_TYPE == 1
273#include <sys/signal.h>
274#include <signal.h>
275#include <unistd.h>
276
277//extern "C" void (*sigset (int sig, void (*disp)(int)))(int);
278
279extern "C" void
280_MiscSigFunc(int val)
281{
282 if (g_signal_func)
283 (*g_signal_func)(val);
284}
285
286extern "C" void
287_MiscSigactionFunc(int val, siginfo_t*,void*)
288{
289 if (g_signal_func)
290 (*g_signal_func)(val);
291}
292
293#endif // STD_SIGNAL_TYPE == 1
294
295/*---------------------------------------------------------------------------*/
296/*---------------------------------------------------------------------------*/
297namespace
298{
299#ifndef USE_SIGACTION
300fSignalFunc default_signal_func_sigsegv = 0;
301fSignalFunc default_signal_func_sigfpe = 0;
302fSignalFunc default_signal_func_sigbus = 0;
303fSignalFunc default_signal_func_sigalrm = 0;
304fSignalFunc default_signal_func_sigvtalrm = 0;
305#endif
306bool global_already_in_signal = false;
307}
308
309extern "C++" ARCANE_UTILS_EXPORT void
310arcaneRedirectSignals(fSignalFunc sig_func)
311{
312 setSignalFunc(sig_func);
313#if STD_SIGNAL_TYPE == 1
314
315#ifdef USE_SIGACTION
316 struct sigaction sa;
317 sa.sa_flags = SA_SIGINFO | SA_NODEFER;
318 sigemptyset(&sa.sa_mask);
319 sa.sa_sigaction = _MiscSigactionFunc;
320
321 sigaction(SIGSEGV, &sa, nullptr); // Segmentation fault.
322 sigaction(SIGFPE, &sa, nullptr); // Floating Exception.
323 sigaction(SIGBUS, &sa, nullptr); // Bus Error.
324 sigaction(SIGALRM, &sa, nullptr); // Signal alarm (ITIMER_REAL)
325 sigaction(SIGVTALRM, &sa, nullptr); // Signal alarm (ITIMER_VIRTUAL)
326#else
327 default_signal_func_sigsegv = sigset(SIGSEGV,_MiscSigFunc); // Segmentation fault.
328 default_signal_func_sigfpe = sigset(SIGFPE ,_MiscSigFunc); // Floating Exception.
329 default_signal_func_sigbus = sigset(SIGBUS ,_MiscSigFunc); // Bus Error.
330 //default_signal_func_sigsys = sigset(SIGSYS ,_MiscSigFunc); // Bad argument in system call.
331 //default_signal_func_sigpipe = sigset(SIGPIPE,_MiscSigFunc); // Pipe error.
332 default_signal_func_sigalrm = sigset(SIGALRM,_MiscSigFunc); // Signal alarm (ITIMER_REAL)
333 default_signal_func_sigvtalrm = sigset(SIGVTALRM,_MiscSigFunc); // Signal alarm (ITIMER_VIRTUAL)
334#endif // USE_SIGACTION
335#endif // STD_SIGNAL_TYPE == 1
336}
337
338extern "C++" ARCANE_UTILS_EXPORT void
339arcaneCallDefaultSignal(int val)
340{
341#if STD_SIGNAL_TYPE == 1
342
343 //fSignalFunc func = 0;
344 SignalException::eSignalType signal_type = SignalException::ST_Unknown;
345
346 switch(val){
347 case SIGSEGV:
348 signal_type = SignalException::ST_SegmentationFault;
349 break;
350 case SIGFPE:
351 signal_type = SignalException::ST_FloatingException;
352 break;
353 case SIGBUS:
354 signal_type = SignalException::ST_BusError;
355 break;
356 case SIGALRM:
357 case SIGVTALRM:
358 signal_type = SignalException::ST_Alarm;
359 break;
360 }
361
362 // cerr << "** SIGVAL " << val << ' ' << SIG_DFL
363 // << ' ' << SIG_IGN << " is_in_signal?=" << global_already_in_signal << '\n';
364
365 // En cas de nouveau signal alors qu'on est déja dans un handler, ou
366 // s'il s'agit d'un signal d'erreur memoire (SIGBUS ou SIGSEGV), on fait un abort.
367 if (global_already_in_signal)
368 ::abort();
369 global_already_in_signal = true;
370
371 arcaneDebugPause("arcaneCallDefaultSignal");
372
373 // Pour éviter certains problèmes lors de la récupération de la pile
374 // qui peuvent provoquer une exception, on récupère d'abord la pile
375 // d'appel et on la passe au constructeur de l'exception.
376 StackTrace stack_trace;
378 if (stack_service){
379 stack_trace = stack_service->stackTrace();
380 cerr << " Signal exception Stack: " << stack_trace.toString() << '\n';
381 }
382 else
383 cerr << " No stack trace service\n";
384
385 // Si demandé, affiche la pile d'appel via le debugger. Cela permet d'avoir
386 // plus d'informations (mais c'est plus long à exécuter)
387 bool do_debug_stack = false;
388 if (auto v = Convert::Type<Int32>::tryParseFromEnvironment("ARCANE_DUMP_DEBUGGER_STACK_IN_SIGNAL", true))
389 do_debug_stack = (v.value()!=0);
390 if (do_debug_stack){
391 std::cerr << "GBDStack pid=" << platform::getProcessId() << " stack=" << platform::getGDBStack() << "\n";
392 }
393 else
394 std::cerr << "SignalCaught: You can dump full stacktrace of the process if environment "
395 "variable ARCANE_DUMP_DEBUGGER_STACK_IN_SIGNAL is set to 1\n";
396
397 if (signal_type==SignalException::ST_Alarm){
398 global_already_in_signal = false;
399 throw TimeoutException("Arcane.Signal",stack_trace);
400 }
401 else if (signal_type==SignalException::ST_FloatingException){
402 global_already_in_signal = false;
403 cerr << "** THROW ARITHMETIC EXCEPTION\n";
404 // Réactive les exceptions flottantes pour le prochain coup
406 throw ArithmeticException(A_FUNCINFO,stack_trace);
407 }
408 throw SignalException("Arcane.Signal",stack_trace,signal_type,val);
409#endif
410}
411
412/*---------------------------------------------------------------------------*/
413/*---------------------------------------------------------------------------*/
414
415/*---------------------------------------------------------------------------*/
416/*---------------------------------------------------------------------------*/
417
418#ifdef ARCANE_DEBUG
419extern "C" void
420_PureVirtual()
421{
422 cerr << "** pure virtual method called\n";
423 //pause();
424}
425#endif
426
427class HexaPrint
428{
429 public:
430 HexaPrint(Real v) : m_v(v) {}
431 public:
432 void write(std::ostream& o) const
433 {
434 char* v = (char*)&m_v;
435 o << m_v << " HEXA(";
436 o << (int)v[0] << '-';
437 o << (int)v[1] << '-';
438 o << (int)v[2] << '-';
439 o << (int)v[3] << '-';
440 o << (int)v[4] << '-';
441 o << (int)v[5] << '-';
442 o << (int)v[6] << '-';
443 o << (int)v[7] << ")";
444 }
445 Real m_v;
446};
447
448ARCANE_UTILS_EXPORT std::ostream&
449operator<<(std::ostream& o,const HexaPrint& hp)
450{
451 hp.write(o);
452 return o;
453}
454
455/*---------------------------------------------------------------------------*/
456/*---------------------------------------------------------------------------*/
457
458} // End namespace Arcane
459
460/*---------------------------------------------------------------------------*/
461/*---------------------------------------------------------------------------*/
462
463/*---------------------------------------------------------------------------*/
464/*---------------------------------------------------------------------------*/
Exception lorsqu'une erreur arithmétique survient.
Classe template pour convertir un type.
Exception lorsqu'une erreur fatale est survenue.
Interface d'un service de trace des appels de fonctions.
Interface d'un service implémentant le support des threads.
Exception lorsqu'un signal survient.
Informations sur la pile d'appel des fonctions.
ARCCORE_BASE_EXPORT IStackTraceService * getStackTraceService()
Service utilisé pour obtenir la pile d'appel.
IThreadImplementation * getThreadImplementationService()
Service utilisé pour gérer les threads.
ARCCORE_BASE_EXPORT int getProcessId()
Numéro du processus.
ARCCORE_BASE_EXPORT void enableFloatingException(bool active)
Active ou désactive les exceptions lors d'un calcul flottant. Cette opération n'est pas supportée sur...
String getGDBStack()
Récupère la pile d'appel via gdb.
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
void arcaneNoReferenceErrorCallTerminate(const void *ptr)
Utilisation d'un objet non référencé.
Definition Misc.cc:172
Int64 arcaneCurrentThread()
Retourne l'identifiant du thread courant.
Definition Misc.cc:109
bool arcaneIsCheck()
Vrai si on est en mode vérification.
Definition Misc.cc:68
bool arcaneHasThread()
Vrai si arcane est compilé avec le support des threads ET qu'ils sont actifs.
Definition Misc.cc:93
std::int64_t Int64
Type entier signé sur 64 bits.
void arcaneSetHasThread(bool v)
Active ou désactive le support des threads.
Definition Misc.cc:99
void arcaneNullPointerError()
Signalue l'utilisation d'un pointeur nul.
void arcanePrintf(const char *,...)
Encapsulation de la fonction C printf.
Definition Misc.cc:182
void(* fDoAssert)(const char *, const char *, const char *, size_t)
Fonction appelée lorsqu'une assertion échoue.
Definition Misc.cc:212
bool arcaneIsDebug()
Vrai si la macro ARCANE_DEBUG est définie.
Definition Misc.cc:80
ARCCORE_BASE_EXPORT void arccoreDebugPause(const char *msg)
Passe en mode pause ou lance une erreur fatale.
void arcaneSetCheck(bool v)
Active ou désactive le mode vérification.
Definition Misc.cc:74
bool(* fCheckDebug)(unsigned int)
Fonction appelée pour indiquer s'il faut afficher l'information de débug.
Definition Misc.cc:214
void arcaneNoReferenceError(const void *ptr)
Utilisation d'un objet non référencé.
Definition Misc.cc:162
bool _checkDebug(unsigned int val)
Definition Misc.cc:242
double Real
Type représentant un réel.
void _doAssert(const char *text, const char *file, const char *func, size_t line)
Definition Misc.cc:225
ARCCORE_BASE_EXPORT void arccoreSetPauseOnError(bool v)
Indique si on l'appel à arccoreDebugPause() effectue une pause.
void arcaneDebugPause(const char *msg)
Passe en mode pause ou lance une erreur fatale.
Definition Misc.cc:127