Arcane  v3.14.10.0
Documentation utilisateur
Chargement...
Recherche...
Aucune correspondance
Misc.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2024 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-2024 */
9/* */
10/* Diverses fonctions */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/utils/ArcanePrecomp.h"
15
16#include "arcane/utils/Iostream.h"
17#include "arcane/utils/ValueConvert.h"
18#include "arcane/utils/StdHeader.h"
19#include "arcane/utils/PlatformUtils.h"
20#include "arcane/utils/FatalErrorException.h"
21#include "arcane/utils/SignalException.h"
22#include "arcane/utils/TimeoutException.h"
23#include "arcane/utils/ArithmeticException.h"
24#include "arcane/utils/IStackTraceService.h"
25#include "arcane/utils/TraceInfo.h"
26#include "arcane/utils/OStringStream.h"
27#include "arcane/utils/IThreadImplementation.h"
28// Pas utilise ici mais necessaire pour charger les symbols dans la DLL
29#include "arcane/utils/NullThreadMng.h"
30#include "arcane/utils/CriticalSection.h"
31
32#include <limits.h>
33#include <math.h>
34#ifndef ARCANE_OS_WIN32
35#include <unistd.h>
36#endif
37#include <time.h>
38#include <stdarg.h>
39#include <stdlib.h>
40#ifndef ARCANE_OS_WIN32
41#include <sys/time.h>
42#endif
43
44#define USE_SIGACTION 1
45
46/*---------------------------------------------------------------------------*/
47/*---------------------------------------------------------------------------*/
48
49namespace Arcane
50{
51
52/*---------------------------------------------------------------------------*/
53/*---------------------------------------------------------------------------*/
54
55extern "C"
56{
57 typedef void (*fSignalFunc)(int);
58}
59
60/*---------------------------------------------------------------------------*/
61/*---------------------------------------------------------------------------*/
62
63template<> ARCANE_UTILS_EXPORT bool builtInGetValue(double& v,const String& s)
64{
65 const char* ptr = s.localstr();
66#ifdef WIN32
67 if(s=="infinity" || s=="inf")
68 {
69 v = std::numeric_limits<double>::infinity();
70 return false;
71 }
72#endif
73 char* ptr2 = 0;
74 v = ::strtod(ptr,&ptr2);
75 return (ptr2!=(ptr+s.length()));
76}
77template<> ARCANE_UTILS_EXPORT bool builtInGetValue(float& v,const String& s)
78{
79 double z = 0.;
80 bool r = builtInGetValue(z,s);
81 v = (float)z;
82 return r;
83}
84template<> ARCANE_UTILS_EXPORT bool builtInGetValue(long& v,const String& s)
85{
86 const char* ptr = s.localstr();
87 char* ptr2 = 0;
88 v = ::strtol(ptr,&ptr2,0);
89 return (ptr2!=(ptr+s.length()));
90}
91template<> ARCANE_UTILS_EXPORT bool builtInGetValue(int& v,const String& s)
92{
93 long z = 0;
94 bool r = builtInGetValue(z,s);
95 v = (int)z;
96 return r;
97}
98template<> ARCANE_UTILS_EXPORT bool builtInGetValue(short& v,const String& s)
99{
100 long z = 0;
101 bool r = builtInGetValue(z,s);
102 v = (short)z;
103 return r;
104}
105template<> ARCANE_UTILS_EXPORT bool builtInGetValue(unsigned long& v,const String& s)
106{
107 const char* ptr = s.localstr();
108 char* ptr2 = 0;
109 v = ::strtoul(ptr,&ptr2,0);
110 return (ptr2!=(ptr+s.length()));
111}
112template<> ARCANE_UTILS_EXPORT bool builtInGetValue(unsigned int& v,const String& s)
113{
114 unsigned long z = 0;
115 bool r = builtInGetValue(z,s);
116 v = (unsigned int)z;
117 return r;
118}
119template<> ARCANE_UTILS_EXPORT bool builtInGetValue(unsigned short& v,const String& s)
120{
121 unsigned long z = 0;
122 bool r = builtInGetValue(z,s);
123 v = (unsigned short)z;
124 return r;
125}
126template<> ARCANE_UTILS_EXPORT bool builtInGetValue(long long& v,const String& s)
127{
128 const char* ptr = s.localstr();
129 char* ptr2 = 0;
130 v = ::strtoll(ptr,&ptr2,0);
131 return (ptr2!=(ptr+s.length()));
132}
133template<> ARCANE_UTILS_EXPORT bool builtInGetValue(unsigned long long& v,const String& s)
134{
135 const char* ptr = s.localstr();
136 char* ptr2 = 0;
137 v = ::strtoull(ptr,&ptr2,0);
138 return (ptr2!=(ptr+s.length()));
139}
140
141/*---------------------------------------------------------------------------*/
142/*---------------------------------------------------------------------------*/
143
144#ifdef ARCANE_CHECK
145static bool global_arcane_is_check = true;
146#else
147static bool global_arcane_is_check = false;
148#endif
149
150extern "C++" ARCANE_UTILS_EXPORT
152{
153 return global_arcane_is_check;
154}
155
156extern "C++" ARCANE_UTILS_EXPORT
157void arcaneSetCheck(bool v)
158{
159 global_arcane_is_check = v;
160}
161
162extern "C++" ARCANE_UTILS_EXPORT
164{
165#ifdef ARCANE_DEBUG
166 return true;
167#else
168 return false;
169#endif
170}
171
172/*---------------------------------------------------------------------------*/
173/*---------------------------------------------------------------------------*/
174
175// Par défaut on a toujours le support des threads
176namespace
177{
178 bool global_arcane_has_thread = true;
179}
180
181extern "C++" ARCANE_UTILS_EXPORT
183{
184 return global_arcane_has_thread;
185}
186
187extern "C++" ARCANE_UTILS_EXPORT
189{
190 if (!v){
191 global_arcane_has_thread = v;
192 return;
193 }
194}
195
196/*---------------------------------------------------------------------------*/
197/*---------------------------------------------------------------------------*/
198
199extern "C++" ARCANE_UTILS_EXPORT
201{
202 if (arcaneHasThread()){
204 if (ti)
205 return ti->currentThread();
206 }
207 return 0;
208}
209
210/*---------------------------------------------------------------------------*/
211/*---------------------------------------------------------------------------*/
212
213extern "C++" ARCANE_UTILS_EXPORT void
214arcaneSetPauseOnError(bool v)
215{
217}
218
219extern "C++" ARCANE_UTILS_EXPORT void
220arcaneDebugPause(const char* msg)
221{
223}
224
225/*---------------------------------------------------------------------------*/
226/*---------------------------------------------------------------------------*/
227
228extern "C++" ARCANE_UTILS_EXPORT void
229arcaneNullPointerError(const void* ptr)
230{
231 ARCANE_UNUSED(ptr);
232 cerr << "** FATAL: Trying to use a null pointer.\n";
233 arcaneDebugPause("arcaneNullPointerError");
234 throw FatalErrorException(A_FUNCINFO);
235}
236
237/*---------------------------------------------------------------------------*/
238/*---------------------------------------------------------------------------*/
239
240namespace
241{
242void _doNoReferenceError(const void* ptr)
243{
244 cerr << "** FATAL: Null reference.\n";
245 cerr << "** FATAL: Trying to use an item not referenced.\n";
246 cerr << "** FATAL: Item is located at memory address " << ptr << ".\n";
247 arcaneDebugPause("arcaneNoReferenceError");
248}
249}
250
251/*---------------------------------------------------------------------------*/
252/*---------------------------------------------------------------------------*/
253
254extern "C++" ARCANE_UTILS_EXPORT void
256{
257 _doNoReferenceError(ptr);
258 throw FatalErrorException(A_FUNCINFO);
259}
260
261/*---------------------------------------------------------------------------*/
262/*---------------------------------------------------------------------------*/
263
264extern "C++" ARCANE_UTILS_EXPORT void
266{
267 _doNoReferenceError(ptr);
268 std::terminate();
269}
270
271/*---------------------------------------------------------------------------*/
272/*---------------------------------------------------------------------------*/
273
274extern "C++" ARCANE_UTILS_EXPORT void
275arcanePrintf(const char* format,...)
276{
277 // \n écrit en meme temps pour éviter des écritures intermédiares parasites
278 char buffer[256];
279 va_list ap;
280 va_start(ap,format);
281 vsnprintf(buffer,256,format,ap);
282 va_end(ap);
283 cerr << buffer << "\n";
284 cout << "*E* " << buffer << "\n";
285}
286
287/*---------------------------------------------------------------------------*/
288/*---------------------------------------------------------------------------*/
289
290extern "C++" ARCANE_UTILS_EXPORT void
291arcaneObsolete(const char* file,const char* func,unsigned long line,const char* text)
292{
293 cerr << file << ':' << func << ':' << line << '\n';
294 cerr << "usage of this function is deprecated";
295 if (text)
296 cerr << ": " << text;
297 cerr << '\n';
298}
299
300
301/*---------------------------------------------------------------------------*/
302/*---------------------------------------------------------------------------*/
303
304/// Fonction appelée lorsqu'une assertion échoue.
305typedef void (*fDoAssert)(const char*,const char*,const char*,size_t);
306/// Fonction appelée pour indiquer s'il faut afficher l'information de débug
307typedef bool (*fCheckDebug)(unsigned int);
308
309static fDoAssert g_do_assert_func = 0;
310static fCheckDebug g_check_debug_func = 0;
311
312/*---------------------------------------------------------------------------*/
313/*---------------------------------------------------------------------------*/
314/*!
315 * Affichage d'une assertion ayant échouée.
316 */
317ARCANE_UTILS_EXPORT void
318_doAssert(const char* text,const char* file,const char* func,size_t line)
319{
320 if (g_do_assert_func)
321 (*g_do_assert_func)(text,file,func,line);
322 else{
323 std::ostringstream ostr;
324 ostr << text << ':' << file << ':' << func << ':' << line << ": ";
325 throw FatalErrorException("Assert",ostr.str());
326 }
327}
328
329/*---------------------------------------------------------------------------*/
330/*---------------------------------------------------------------------------*/
331/**
332 * Vérifie si un message de débug doit être affiché.
333 */
334extern "C++" ARCANE_UTILS_EXPORT bool
335_checkDebug(unsigned int val)
336{
337 if (g_check_debug_func)
338 return (*g_check_debug_func)(val);
339 return false;
340}
341
342/*---------------------------------------------------------------------------*/
343/*---------------------------------------------------------------------------*/
344
345namespace
346{
347static fSignalFunc g_signal_func = 0;
348}
349
350fSignalFunc
351setSignalFunc(fSignalFunc func)
352{
353 fSignalFunc old = g_signal_func;
354 g_signal_func = func;
355 return old;
356}
357
358/*---------------------------------------------------------------------------*/
359/*---------------------------------------------------------------------------*/
360
361#ifdef ARCANE_OS_LINUX
362#define STD_SIGNAL_TYPE 1
363#endif
364
365#if STD_SIGNAL_TYPE == 1
366#include <sys/signal.h>
367#include <signal.h>
368#include <unistd.h>
369
370//extern "C" void (*sigset (int sig, void (*disp)(int)))(int);
371
372extern "C" void
373_MiscSigFunc(int val)
374{
375 if (g_signal_func)
376 (*g_signal_func)(val);
377}
378
379extern "C" void
380_MiscSigactionFunc(int val, siginfo_t*,void*)
381{
382 if (g_signal_func)
383 (*g_signal_func)(val);
384}
385
386#endif // STD_SIGNAL_TYPE == 1
387
388/*---------------------------------------------------------------------------*/
389/*---------------------------------------------------------------------------*/
390namespace
391{
392#ifndef USE_SIGACTION
393fSignalFunc default_signal_func_sigsegv = 0;
394fSignalFunc default_signal_func_sigfpe = 0;
395fSignalFunc default_signal_func_sigbus = 0;
396fSignalFunc default_signal_func_sigalrm = 0;
397fSignalFunc default_signal_func_sigvtalrm = 0;
398#endif
399bool global_already_in_signal = false;
400}
401
402extern "C++" ARCANE_UTILS_EXPORT void
403arcaneRedirectSignals(fSignalFunc sig_func)
404{
405 setSignalFunc(sig_func);
406#if STD_SIGNAL_TYPE == 1
407
408#ifdef USE_SIGACTION
409 struct sigaction sa;
410 sa.sa_flags = SA_SIGINFO | SA_NODEFER;
411 sigemptyset(&sa.sa_mask);
412 sa.sa_sigaction = _MiscSigactionFunc;
413
414 sigaction(SIGSEGV, &sa, nullptr); // Segmentation fault.
415 sigaction(SIGFPE, &sa, nullptr); // Floating Exception.
416 sigaction(SIGBUS, &sa, nullptr); // Bus Error.
417 sigaction(SIGALRM, &sa, nullptr); // Signal alarm (ITIMER_REAL)
418 sigaction(SIGVTALRM, &sa, nullptr); // Signal alarm (ITIMER_VIRTUAL)
419#else
420 default_signal_func_sigsegv = sigset(SIGSEGV,_MiscSigFunc); // Segmentation fault.
421 default_signal_func_sigfpe = sigset(SIGFPE ,_MiscSigFunc); // Floating Exception.
422 default_signal_func_sigbus = sigset(SIGBUS ,_MiscSigFunc); // Bus Error.
423 //default_signal_func_sigsys = sigset(SIGSYS ,_MiscSigFunc); // Bad argument in system call.
424 //default_signal_func_sigpipe = sigset(SIGPIPE,_MiscSigFunc); // Pipe error.
425 default_signal_func_sigalrm = sigset(SIGALRM,_MiscSigFunc); // Signal alarm (ITIMER_REAL)
426 default_signal_func_sigvtalrm = sigset(SIGVTALRM,_MiscSigFunc); // Signal alarm (ITIMER_VIRTUAL)
427#endif // USE_SIGACTION
428#endif // STD_SIGNAL_TYPE == 1
429}
430
431extern "C++" ARCANE_UTILS_EXPORT void
432arcaneCallDefaultSignal(int val)
433{
434#if STD_SIGNAL_TYPE == 1
435
436 //fSignalFunc func = 0;
437 SignalException::eSignalType signal_type = SignalException::ST_Unknown;
438
439 switch(val){
440 case SIGSEGV:
441 signal_type = SignalException::ST_SegmentationFault;
442 break;
443 case SIGFPE:
444 signal_type = SignalException::ST_FloatingException;
445 break;
446 case SIGBUS:
447 signal_type = SignalException::ST_BusError;
448 break;
449 case SIGALRM:
450 case SIGVTALRM:
451 signal_type = SignalException::ST_Alarm;
452 break;
453 }
454
455 // cerr << "** SIGVAL " << val << ' ' << SIG_DFL
456 // << ' ' << SIG_IGN << " is_in_signal?=" << global_already_in_signal << '\n';
457
458 // En cas de nouveau signal alors qu'on est déja dans un handler, ou
459 // s'il s'agit d'un signal d'erreur memoire (SIGBUS ou SIGSEGV), on fait un abort.
460 if (global_already_in_signal)
461 ::abort();
462 global_already_in_signal = true;
463
464 arcaneDebugPause("arcaneCallDefaultSignal");
465
466 // Pour éviter certains problèmes lors de la récupération de la pile
467 // qui peuvent provoquer une exception, on récupère d'abord la pile
468 // d'appel et on la passe au constructeur de l'exception.
469 StackTrace stack_trace;
470 IStackTraceService* stack_service = platform::getStackTraceService();
471 if (stack_service){
472 stack_trace = stack_service->stackTrace();
473 cerr << " Signal exception Stack: " << stack_trace.toString() << '\n';
474 }
475 else
476 cerr << " No stack trace service\n";
477
478 // Si demandé, affiche la pile d'appel via le debugger. Cela permet d'avoir
479 // plus d'informations (mais c'est plus long à exécuter)
480 bool do_debug_stack = false;
481 if (auto v = Convert::Type<Int32>::tryParseFromEnvironment("ARCANE_DUMP_DEBUGGER_STACK_IN_SIGNAL", true))
482 do_debug_stack = (v.value()!=0);
483 if (do_debug_stack){
484 std::cerr << "GBDStack pid=" << platform::getProcessId() << " stack=" << platform::getGDBStack() << "\n";
485 }
486 else
487 std::cerr << "SignalCaught: You can dump full stacktrace of the process if environment "
488 "variable ARCANE_DUMP_DEBUGGER_STACK_IN_SIGNAL is set to 1\n";
489
490 if (signal_type==SignalException::ST_Alarm){
491 global_already_in_signal = false;
492 throw TimeoutException("Arcane.Signal",stack_trace);
493 }
494 else if (signal_type==SignalException::ST_FloatingException){
495 global_already_in_signal = false;
496 cerr << "** THROW ARITHMETIC EXCEPTION\n";
497 // Réactive les exceptions flottantes pour le prochain coup
498 platform::enableFloatingException(true);
499 throw ArithmeticException(A_FUNCINFO,stack_trace);
500 }
501 throw SignalException("Arcane.Signal",stack_trace,signal_type,val);
502#endif
503}
504
505/*---------------------------------------------------------------------------*/
506/*---------------------------------------------------------------------------*/
507
508/*---------------------------------------------------------------------------*/
509/*---------------------------------------------------------------------------*/
510
511#ifdef ARCANE_DEBUG
512extern "C" void
513_PureVirtual()
514{
515 cerr << "** pure virtual method called\n";
516 //pause();
517}
518#endif
519
521{
522 public:
523 HexaPrint(Real v) : m_v(v) {}
524 public:
525 void write(std::ostream& o) const
526 {
527 char* v = (char*)&m_v;
528 o << m_v << " HEXA(";
529 o << (int)v[0] << '-';
530 o << (int)v[1] << '-';
531 o << (int)v[2] << '-';
532 o << (int)v[3] << '-';
533 o << (int)v[4] << '-';
534 o << (int)v[5] << '-';
535 o << (int)v[6] << '-';
536 o << (int)v[7] << ")";
537 }
538 Real m_v;
539};
540
541ARCANE_UTILS_EXPORT std::ostream&
542operator<<(std::ostream& o,const HexaPrint& hp)
543{
544 hp.write(o);
545 return o;
546}
547
548/*---------------------------------------------------------------------------*/
549/*---------------------------------------------------------------------------*/
550
551} // End namespace Arcane
552
553/*---------------------------------------------------------------------------*/
554/*---------------------------------------------------------------------------*/
555
556/*---------------------------------------------------------------------------*/
557/*---------------------------------------------------------------------------*/
Exception lorsqu'une erreur fatale est survenue.
Interface d'un service implémentant le support des threads.
IThreadImplementation * getThreadImplementationService()
Service utilisé pour gérer les threads.
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:265
Int64 arcaneCurrentThread()
Retourne l'identifiant du thread courant.
Definition Misc.cc:200
bool arcaneIsCheck()
Vrai si on est en mode vérification.
Definition Misc.cc:151
bool arcaneHasThread()
Vrai si arcane est compilé avec le support des threads ET qu'ils sont actifs.
Definition Misc.cc:182
void arcaneSetHasThread(bool v)
Active ou désactive le support des threads.
Definition Misc.cc:188
void arcaneNullPointerError()
Signalue l'utilisation d'un pointeur nul.
void arcanePrintf(const char *,...)
Encapsulation de la fonction C printf.
Definition Misc.cc:275
void(* fDoAssert)(const char *, const char *, const char *, size_t)
Fonction appelée lorsqu'une assertion échoue.
Definition Misc.cc:305
bool arcaneIsDebug()
Vrai si la macro ARCANE_DEBUG est définie.
Definition Misc.cc:163
void arcaneSetCheck(bool v)
Active ou désactive le mode vérification.
Definition Misc.cc:157
bool(* fCheckDebug)(unsigned int)
Fonction appelée pour indiquer s'il faut afficher l'information de débug.
Definition Misc.cc:307
void arcaneNoReferenceError(const void *ptr)
Utilisation d'un objet non référencé.
Definition Misc.cc:255
bool _checkDebug(unsigned int val)
Definition Misc.cc:335
void _doAssert(const char *text, const char *file, const char *func, size_t line)
Definition Misc.cc:318
void arcaneDebugPause(const char *msg)
Passe en mode pause ou lance une erreur fatale.
Definition Misc.cc:220
std::ostream & operator<<(std::ostream &ostr, eItemKind item_kind)
Opérateur de sortie sur un flot.
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.