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