Arcane  v3.15.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{
102}
103
104extern "C++" ARCANE_UTILS_EXPORT
106{
107 if (!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
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{
175 throw FatalErrorException(A_FUNCINFO);
176}
177
178/*---------------------------------------------------------------------------*/
179/*---------------------------------------------------------------------------*/
180
181extern "C++" ARCANE_UTILS_EXPORT void
183{
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;
387 IStackTraceService* stack_service = platform::getStackTraceService();
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
415 platform::enableFloatingException(true);
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
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/*---------------------------------------------------------------------------*/
Lecteur des fichiers de maillage via la bibliothèque LIMA.
Definition Lima.cc:149
Exception lorsqu'une erreur fatale est survenue.
Interface d'un service implémentant le support des threads.
std::ostream & operator<<(std::ostream &o, eExecutionPolicy exec_policy)
Affiche le nom de la politique d'exécution.
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: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
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
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.