Arcane  v3.15.0.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
ArcaneMain.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/* ArcaneMain.cc (C) 2000-2025 */
9/* */
10/* Classe gérant l'exécution. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/impl/ArcaneMain.h"
15
16#include "arcane/utils/Iostream.h"
17#include "arcane/utils/List.h"
18#include "arcane/utils/Iterator.h"
19#include "arcane/utils/ScopedPtr.h"
20#include "arcane/utils/PlatformUtils.h"
21#include "arcane/utils/FatalErrorException.h"
22#include "arcane/utils/ParallelFatalErrorException.h"
23#include "arcane/utils/OStringStream.h"
24#include "arcane/utils/ApplicationInfo.h"
25#include "arcane/utils/ValueConvert.h"
26#include "arcane/utils/ITraceMng.h"
27#include "arcane/utils/SignalException.h"
28#include "arcane/utils/TimeoutException.h"
29#include "arcane/utils/NotImplementedException.h"
30#include "arcane/utils/ArithmeticException.h"
31#include "arcane/utils/StringBuilder.h"
32#include "arcane/utils/IDynamicLibraryLoader.h"
33#include "arcane/utils/CheckedConvert.h"
34#include "arcane/utils/CommandLineArguments.h"
35#include "arcane/utils/TestLogger.h"
37#include "arcane/utils/internal/MemoryUtilsInternal.h"
38#include "arcane/utils/internal/ValueConvertInternal.h"
39
40#include "arcane/core/IMainFactory.h"
41#include "arcane/core/IApplication.h"
42#include "arcane/core/IServiceLoader.h"
43#include "arcane/core/IParallelMng.h"
44#include "arcane/core/IParallelSuperMng.h"
45#include "arcane/core/IIOMng.h"
46#include "arcane/core/ISession.h"
47#include "arcane/core/ISubDomain.h"
48#include "arcane/core/IRessourceMng.h"
49#include "arcane/core/IModuleMng.h"
50#include "arcane/core/IModule.h"
51#include "arcane/core/IVariableMng.h"
52#include "arcane/core/VariableRef.h"
53#include "arcane/core/ITimeLoopMng.h"
54#include "arcane/core/ITimeLoop.h"
55#include "arcane/core/Directory.h"
56#include "arcane/core/XmlNodeList.h"
57#include "arcane/core/IXmlDocumentHolder.h"
58#include "arcane/core/ItemTypeMng.h"
59#include "arcane/core/ServiceUtils.h"
60#include "arcane/core/ICodeService.h"
61#include "arcane/core/CaseOptions.h"
62#include "arcane/core/VariableCollection.h"
63#include "arcane/core/ItemGroupImpl.h"
64#include "arcane/core/SubDomainBuildInfo.h"
65#include "arcane/core/ICaseMng.h"
66#include "arcane/core/DotNetRuntimeInitialisationInfo.h"
67#include "arcane/core/AcceleratorRuntimeInitialisationInfo.h"
68#include "arcane/core/ApplicationBuildInfo.h"
69
70#include "arcane/core/IServiceFactory.h"
71#include "arcane/core/IModuleFactory.h"
72
73#include "arcane/impl/MainFactory.h"
74#include "arcane/impl/InternalInfosDumper.h"
75#include "arcane/impl/internal/ArcaneMainExecInfo.h"
76#include "arcane/impl/internal/ThreadBindingMng.h"
77
78#include "arcane/accelerator/core/internal/RegisterRuntimeInfo.h"
79
80#include "arcane_internal_config.h"
81
82#include <signal.h>
83#include <exception>
84#ifndef ARCANE_OS_WIN32
85#include <unistd.h>
86#include <sys/stat.h>
87#include <fcntl.h>
88#endif
89
90#include <set>
91#include <map>
92#include <chrono>
93
94#ifdef ARCANE_FLEXLM
95#include "arcane/impl/FlexLMTools.h"
96#endif
97
98/*---------------------------------------------------------------------------*/
99/*---------------------------------------------------------------------------*/
100namespace Arcane
101{
103{
104 public:
105
106 List<IServiceFactoryInfo*> m_service_factory_infos;
107 List<IModuleFactoryInfo*> m_module_factory_infos;
108 List<IApplicationBuildInfoVisitor*> m_application_build_info_visitors;
109 ApplicationBuildInfo m_app_build_info;
110 DotNetRuntimeInitialisationInfo m_dotnet_init_info;
111 AcceleratorRuntimeInitialisationInfo m_accelerator_init_info;
112 bool m_has_dotnet_wrapper = false;
113 String m_dotnet_assembly;
114 String m_arcane_lib_path;
115 IDirectSubDomainExecuteFunctor* m_direct_exec_functor = nullptr;
117 std::atomic<Int32> m_nb_autodetect = 0;
122};
123} // namespace Arcane
124
125namespace
126{
127Arcane::ArcaneMainStaticInfo* global_static_info = nullptr;
128Arcane::ArcaneMainStaticInfo* _staticInfo()
129{
130 // TODO: voir s'il faut protéger en multi-threading.
131 if (!global_static_info)
132 global_static_info = new Arcane::ArcaneMainStaticInfo();
133 return global_static_info;
134}
135void _deleteStaticInfo()
136{
137 delete global_static_info;
138 global_static_info = nullptr;
139}
140} // namespace
141
142/*---------------------------------------------------------------------------*/
143/*---------------------------------------------------------------------------*/
144
145extern "C" void arcaneEndProgram()
146{
147 // Juste la pour faire un point d'entrée à third.
148}
149
150/*---------------------------------------------------------------------------*/
151/*---------------------------------------------------------------------------*/
152
153extern "C" {
154typedef void (*fSignalFunc)(int);
155void arcaneSignalHandler(int);
156}
157
158/*---------------------------------------------------------------------------*/
159/*---------------------------------------------------------------------------*/
160
161namespace Arcane
162{
163
164/*---------------------------------------------------------------------------*/
165/*---------------------------------------------------------------------------*/
166
167extern "C++" ARCANE_UTILS_EXPORT void
168arcaneRedirectSignals(fSignalFunc sig_func);
169
170extern "C++" ARCANE_UTILS_EXPORT void
171arcaneCallDefaultSignal(int val);
172
173extern "C++" ARCANE_UTILS_EXPORT void
174initializeStringConverter();
175
176extern "C++" ARCANE_IMPL_EXPORT IArcaneMain*
177createArcaneMainBatch(const ApplicationInfo& exe_info, IMainFactory*);
178
179extern "C++" ARCANE_IMPL_EXPORT IDynamicLibraryLoader*
180createGlibDynamicLibraryLoader();
181
182extern "C++" ARCANE_IMPL_EXPORT ICodeService*
183createArcaneCodeService(IApplication* app);
184
185extern "C++" ARCANE_UTILS_EXPORT void
186arcanePrintSpecificMemoryStats();
187
188std::atomic<Int32> ArcaneMain::m_nb_arcane_init(0);
189std::atomic<Int32> ArcaneMain::m_is_init_done(0);
190bool ArcaneMain::m_has_garbage_collector = false;
191bool ArcaneMain::m_is_master_io = true;
192bool ArcaneMain::m_is_use_test_logger = false;
193
194/*---------------------------------------------------------------------------*/
195/*---------------------------------------------------------------------------*/
196
198: public MainFactory
199{
200 public:
201
203 {
204 return createArcaneMainBatch(app_info, this);
205 }
206};
207
208/*---------------------------------------------------------------------------*/
209/*---------------------------------------------------------------------------*/
210
212{
213 public:
214
215 Impl(const ApplicationInfo& infos)
216 : m_app_info(infos)
217 , m_application_build_info(ArcaneMain::defaultApplicationBuildInfo())
220 {}
224 : m_app_info(infos)
225 , m_application_build_info(build_infos)
226 , m_dotnet_info(dotnet_info)
227 , m_accelerator_info(accelerator_info)
228 {}
229
230 public:
231
232 ApplicationInfo m_app_info;
233 ApplicationBuildInfo m_application_build_info;
235 AcceleratorRuntimeInitialisationInfo m_accelerator_info;
236 ThreadBindingMng m_thread_binding_mng;
237};
238
239/*---------------------------------------------------------------------------*/
240/*---------------------------------------------------------------------------*/
241
242/*---------------------------------------------------------------------------*/
243/*---------------------------------------------------------------------------*/
244
245void ArcaneMain::
246redirectSignals()
247{
248 bool redirect_signals = true;
249 String rv = platform::getEnvironmentVariable("ARCANE_REDIRECT_SIGNALS");
250 (void)builtInGetValue(redirect_signals, rv);
251 if (redirect_signals) {
252 arcaneRedirectSignals(arcaneSignalHandler);
253 }
254}
255
256/*---------------------------------------------------------------------------*/
257/*---------------------------------------------------------------------------*/
258
259void ArcaneMain::
260setUseTestLogger(bool v)
261{
262 m_is_use_test_logger = v;
263}
264
265/*---------------------------------------------------------------------------*/
266/*---------------------------------------------------------------------------*/
267
270{
271 m_default_main_factory = mf;
272}
273
274/*---------------------------------------------------------------------------*/
275/*---------------------------------------------------------------------------*/
276
278: public IFunctor
279{
280 public:
281
283 : m_app_info(app_info)
284 , m_exec_main(exec_main)
285 {
286 }
287
288 public:
289
290 void executeFunctor() override
291 {
292 StringList args;
293 m_app_info.args(args);
294 if (!m_exec_main->parseArgs(args))
295 m_exec_main->execute();
296 }
297
298 private:
299
300 const ApplicationInfo& m_app_info;
301 IArcaneMain* m_exec_main;
302};
303
304/*---------------------------------------------------------------------------*/
305/*---------------------------------------------------------------------------*/
313{
314 public:
315
316 Int32 check()
317 {
318 auto* x = _staticInfo();
319 if (x->m_nb_autodetect > 0)
320 return x->m_autodetect_return_value;
321
322 ArcaneMain::_setArcaneLibraryPath();
323
324 std::chrono::high_resolution_clock clock;
325
326 // TODO: rendre thread-safe
327 {
328 ArcaneMain::_checkAutoDetectMPI();
329
330 bool has_accelerator = false;
331 // Mesure le temps de l'initialisation.
332 // Comme ici on n'a pas encore initialié Arcane il ne faut
333 // pas utiliser de méthode du namespace 'platform'.
334 auto start_time = clock.now();
335 x->m_autodetect_return_value = ArcaneMain::_checkAutoDetectAccelerator(has_accelerator);
336 auto end_time = clock.now();
337 // Ne récupère le temps que si on a utilise un accélérateur
338 if (has_accelerator)
339 x->m_init_time_accelerator = _getTime(end_time,start_time);
340 ++x->m_nb_autodetect;
341 }
342 return x->m_autodetect_return_value;
343 }
344
345 template<typename TimeType>
346 Real _getTime(TimeType end_time,TimeType start_time)
347 {
348 auto duration = std::chrono::duration_cast<std::chrono::nanoseconds>(end_time - start_time);
349 Real x = static_cast<Real>(duration.count());
350 return x / 1.0e9;
351 }
352};
353
354/*---------------------------------------------------------------------------*/
355/*---------------------------------------------------------------------------*/
367{
368 if (m_exec_main)
369 return 0;
370
371 m_ret_val = 0;
372 m_clean_abort = false;
373
374 ArcaneMain::redirectSignals();
375
376 // Création de la classe d'exécution
377 try {
378 if (m_has_build_info) {
379 ArcaneMain* x = new ArcaneMain(m_app_info, m_main_factory,
380 m_application_build_info,
383 m_exec_main = x;
384 }
385 else {
386 m_exec_main = m_main_factory->createArcaneMain(m_app_info);
387 }
388 m_exec_main->build();
389 ArcaneMain::m_is_master_io = m_exec_main->application()->parallelSuperMng()->isMasterIO();
390 m_exec_main->initialize();
391 IArcaneMain::setArcaneMain(m_exec_main);
392 }
393 catch (const ArithmeticException& ex) {
394 cerr << "** CATCH ARITHMETIC_EXCEPTION\n";
395 return arcanePrintArcaneException(ex, nullptr);
396 }
397 catch (const Exception& ex) {
398 return arcanePrintArcaneException(ex, nullptr);
399 }
400 catch (const std::exception& ex) {
401 return arcanePrintStdException(ex, nullptr);
402 }
403 catch (...) {
404 return arcanePrintAnyException(nullptr);
405 }
406
407 // Redirige a nouveau les signaux car certaines
408 // routines d'initialisation (par exemple MPI) peuvent
409 // les detourner.
410 ArcaneMain::redirectSignals();
411
412 m_ret_val = 0;
413 m_clean_abort = false;
414
415#ifdef ARCANE_FLEXLM
416 try {
417 IApplication* app = m_exec_main->application();
418 ITraceMng* trace = app->traceMng();
419 IParallelSuperMng* parallel_super_mng = app->parallelSuperMng();
420 trace->info() << "Initializing license manager";
422
423 // La politique de licence parallèle est sous-traitée aux applications
424 // bool is_parallel = parallel_super_mng->isParallel();
425 // FlexLMTools<ArcaneFeatureModel> license_tool;
426 // Integer commSize = parallel_super_mng->commSize();
427 // if (is_parallel && commSize > 1)
428 // { // La fonctionnalité paralléle n'est activé que si nécessaire
429 // license_tool.getLicense(ArcaneFeatureModel::ArcaneParallel,commSize);
430 // }
431 }
432 catch (const Exception& ex) {
433 IApplication* app = m_exec_main->application();
434 ITraceMng* trace = app->traceMng();
435 m_ret_val = arcanePrintArcaneException(ex, trace);
436 if (ex.isCollective()) {
437 m_clean_abort = true;
438 }
439 }
440#endif
441 return 0;
442}
443
444/*---------------------------------------------------------------------------*/
445/*---------------------------------------------------------------------------*/
446// NOTE: Cette méthode ne doit pas lancer d'exceptions
447void ArcaneMainExecInfo::
448execute()
449{
450 if (m_ret_val != 0)
451 return;
452
453 if (m_direct_exec_functor)
454 m_exec_main->setDirectExecuteFunctor(m_direct_exec_functor);
455
457 if (ArcaneMain::m_exec_override_functor) {
458 // Obsolète. Ne plus utiliser.
459 IApplication* app = m_exec_main->application();
460 ArcaneMain::m_exec_override_functor->m_application = app;
461 ITraceMng* trace = app->traceMng();
462 trace->info() << "Calling overriding functor";
463 m_ret_val = ArcaneMain::callFunctorWithCatchedException(ArcaneMain::m_exec_override_functor->functor(),
464 m_exec_main, &m_clean_abort, true);
465 }
466 else
467 m_ret_val = ArcaneMain::callFunctorWithCatchedException(&exec_functor, m_exec_main, &m_clean_abort, true);
468}
469
470/*---------------------------------------------------------------------------*/
471/*---------------------------------------------------------------------------*/
472
473void ArcaneMainExecInfo::
474finalize()
475{
476 // Désactive les exceptions flottantes
477 platform::enableFloatingException(false);
478
479 // Si l'exécution s'est bien déroulée mais que l'utilisateur a spécifié un
480 // code d'erreur, on le récupère.
481 int exe_error_code = m_exec_main->errorCode();
482 if (m_ret_val == 0 && exe_error_code != 0) {
483 m_ret_val = exe_error_code;
484 }
485 else if (m_ret_val != 0)
486 m_exec_main->setErrorCode(m_ret_val);
487
488 m_exec_main->finalize();
489
490 if (m_ret_val != 0 && !m_clean_abort)
491 m_exec_main->doAbort();
492
493 // Destruction du code.
494 // Attention à ne pas détruire le gestionnaire avant car lorsqu'une exception
495 // de l'architecture est générée, elle utilise un ITraceMng pour afficher
496 // le message
497 delete m_exec_main;
498 m_exec_main = nullptr;
499#ifndef ARCANE_USE_MPC
500 IArcaneMain::setArcaneMain(m_exec_main);
501#endif
502}
503
504/*---------------------------------------------------------------------------*/
505/*---------------------------------------------------------------------------*/
512{
513 if (!factory)
514 return 5;
515
517 int r = exec_info.initialize();
518 if (r != 0)
519 return r;
520
521 IDirectSubDomainExecuteFunctor* func = _staticInfo()->m_direct_exec_functor;
522 if (func)
523 exec_info.setDirectExecFunctor(func);
524 exec_info.execute();
525 exec_info.finalize();
526
527 return exec_info.returnValue();
528}
529
530/*---------------------------------------------------------------------------*/
531/*---------------------------------------------------------------------------*/
532
535 bool* clean_abort, bool is_print)
536{
537 int ret_val = 0;
538 *clean_abort = false;
539 IApplication* app = exec_main->application();
540 ITraceMng* trace = app->traceMng();
541 bool is_parallel = app->parallelSuperMng()->isParallel();
542 bool is_master = app->parallelSuperMng()->isMasterIO();
543 try {
544 functor->executeFunctor();
545 }
546 catch (const FatalErrorException& ex) {
547 if (ex.isCollective()) {
548 if (is_parallel) {
549 *clean_abort = true;
550 ret_val = 5;
551 if (is_master && is_print) {
552 std::ofstream ofile("fatal");
553 ofile << ret_val << '\n';
554 ofile.flush();
555 trace->error() << "ParallelFatalErrorException caught in ArcaneMain::callFunctor: " << ex << '\n';
556 }
557 }
558 else {
559 trace->error() << "ParallelFatalErrorException caught in ArcaneMain::callFunctor: " << ex << '\n';
560 ret_val = 4;
561 }
562 }
563 else {
564 trace->error() << Trace::Color::red() << "FatalErrorException caught in ArcaneMain::callFunctor: " << ex << '\n';
565 ret_val = 4;
566 }
567 }
568 catch (const SignalException& ex) {
569 trace->error() << "SignalException caught in ArcaneMain::callFunctor: " << ex << '\n';
570 ret_val = 6;
571 }
572 catch (const TimeoutException& ex) {
573 trace->error() << "TimeoutException caught in ArcaneMain::callFunctor: " << ex << '\n';
574 ret_val = 7;
575 }
576 catch (const ParallelFatalErrorException& ex) {
577 // TODO: utiliser le code de FatalErrorException en mode collectif.n
578 if (is_parallel) {
579 *clean_abort = true;
580 ret_val = 5;
581 if (is_master && is_print) {
582 std::ofstream ofile("fatal");
583 ofile << ret_val << '\n';
584 ofile.flush();
585 trace->error() << "ParallelFatalErrorException caught in ArcaneMain::callFunctor: " << ex << '\n';
586 }
587 }
588 else {
589 trace->error() << "ParallelFatalErrorException caught in ArcaneMain::callFunctor: " << ex << '\n';
590 ret_val = 4;
591 }
592 }
593 catch (const ArithmeticException& ex) {
594 cerr << "** ARITHMETIC EXCEPTION!\n";
595 ret_val = arcanePrintArcaneException(ex, trace);
596 if (ex.isCollective()) {
597 *clean_abort = true;
598 }
599 }
600 catch (const Exception& ex) {
601 ret_val = arcanePrintArcaneException(ex, trace);
602 if (ex.isCollective()) {
603 *clean_abort = true;
604 }
605 }
606 catch (const std::exception& ex) {
607 ret_val = arcanePrintStdException(ex, trace);
608 }
609 catch (...) {
610 ret_val = arcanePrintAnyException(trace);
611 }
612 return ret_val;
613}
614
615/*---------------------------------------------------------------------------*/
616/*---------------------------------------------------------------------------*/
617
618void ArcaneMain::
619_launchMissingInitException()
620{
621 cerr << "ArcaneMain: appel ArcaneMain::arcaneInitialize() manquant.\n";
622 throw std::exception();
623}
624
625/*---------------------------------------------------------------------------*/
626/*---------------------------------------------------------------------------*/
627
628void ArcaneMain::
629_checkHasInit()
630{
631 if (m_nb_arcane_init <= 0)
632 _launchMissingInitException();
633}
634
635/*---------------------------------------------------------------------------*/
636/*---------------------------------------------------------------------------*/
637
638extern "C++" void arcaneInitCheckMemory();
639extern "C++" void arcaneExitCheckMemory();
640
641/*---------------------------------------------------------------------------*/
642/*---------------------------------------------------------------------------*/
643
646{
647 if (m_nb_arcane_init != 0) {
648 cerr << "WARNING: ArcaneMain::setHasGarbageCollector has to be called before arcaneInitialize\n";
649 return;
650 }
651 m_has_garbage_collector = true;
652}
653
654/*---------------------------------------------------------------------------*/
655/*---------------------------------------------------------------------------*/
656
659{
660 if (m_nb_arcane_init != 0) {
661 cerr << "WARNING: ArcaneMain::setHasDotNETRuntime has to be called before arcaneInitialize\n";
662 return;
663 }
665}
666
667/*---------------------------------------------------------------------------*/
668/*---------------------------------------------------------------------------*/
669
672{
673 m_exec_override_functor = functor;
674}
675
676/*---------------------------------------------------------------------------*/
677/*---------------------------------------------------------------------------*/
678
681{
682 return _staticInfo()->m_has_dotnet_wrapper;
683}
684
685/*---------------------------------------------------------------------------*/
686/*---------------------------------------------------------------------------*/
687/*
688 * \brief Positionne le chemin contenant les bibliothèques dynamiques de Arcane.
689 *
690 * Il ne faut appeler qu'une seule fois cette méthode.
691 */
692void ArcaneMain::
693_setArcaneLibraryPath()
694{
697 if (!dll_full_path.null())
698 dir_name = platform::getFileDirName(dll_full_path);
699 if (dir_name.null())
700 dir_name = platform::getCurrentDirectory();
701 _staticInfo()->m_arcane_lib_path = dir_name;
702}
703
704/*---------------------------------------------------------------------------*/
705/*---------------------------------------------------------------------------*/
706
707void ArcaneMain::
708_checkCreateDynamicLibraryLoader()
709{
711 if (!x) {
712 platform::setDynamicLibraryLoader(createGlibDynamicLibraryLoader());
713 }
714}
715
716/*---------------------------------------------------------------------------*/
717/*---------------------------------------------------------------------------*/
718
721{
722 // Le premier thread qui arrive ici fait l'init.
723 // Les autres doivent attendre que l'init soit terminée.
724 if (m_nb_arcane_init.fetch_add(1) == 0) {
725 (void)_staticInfo();
726 Exception::staticInit();
727 dom::DOMImplementation::initialize();
729
730 // Regarde si on souhaite utiliser l'ancien mécanisme (avant la 3.15)
731 // pour convertir les chaînes de caractères en types numériques
732 if (auto v = Convert::Type<Int32>::tryParseFromEnvironment("ARCANE_USE_LEGACY_BUILTINVALUECONVERT", true))
733 impl::arcaneSetIsValueConvertUseFromChars(v.value()==0);
734
735 // Crée le singleton gestionnaire des types
737 initializeStringConverter();
738 arcaneInitCheckMemory();
739 // Initialise le singleton du groupe vide et garde une référence dessus.
741 _checkCreateDynamicLibraryLoader();
742 m_is_init_done = 1;
743 }
744 else
745 // Attend que le thread qui fait l'init ait terminé
746 while (m_is_init_done.load() == 0)
747 ;
748}
749
750/*---------------------------------------------------------------------------*/
751/*---------------------------------------------------------------------------*/
752
755{
756 _checkHasInit();
757
758 if (m_nb_arcane_init.fetch_sub(1) == 1) {
760
763
764 {
766 if (x) {
767 x->closeLibraries();
768 delete x;
770 }
771 }
772 arcanePrintSpecificMemoryStats();
773 arcaneExitCheckMemory();
775 dom::DOMImplementation::terminate();
777 arcaneEndProgram();
778#ifdef ARCANE_FLEXLM
779 {
780 FlexLMMng::instance()->releaseAllLicenses();
781 }
782#endif
783 m_is_init_done = 0;
784 }
785}
786
787/*---------------------------------------------------------------------------*/
788/*---------------------------------------------------------------------------*/
789
792{
793 _staticInfo()->m_service_factory_infos.add(sri);
794}
795
796/*---------------------------------------------------------------------------*/
797/*---------------------------------------------------------------------------*/
798
801{
802 _staticInfo()->m_module_factory_infos.add(mfi);
803}
804
805/*---------------------------------------------------------------------------*/
806/*---------------------------------------------------------------------------*/
807
810{
811 _staticInfo()->m_application_build_info_visitors.add(visitor);
812}
813
814/*---------------------------------------------------------------------------*/
815/*---------------------------------------------------------------------------*/
816
819{
820 return _staticInfo()->m_app_build_info._internalApplicationInfo();
821}
822
823/*---------------------------------------------------------------------------*/
824/*---------------------------------------------------------------------------*/
825
831
832/*---------------------------------------------------------------------------*/
833/*---------------------------------------------------------------------------*/
834
840
841/*---------------------------------------------------------------------------*/
842/*---------------------------------------------------------------------------*/
843
846{
847 return _staticInfo()->m_app_build_info;
848}
849
850/*---------------------------------------------------------------------------*/
851/*---------------------------------------------------------------------------*/
852
855{
856 return m_p->m_application_build_info;
857}
858
859/*---------------------------------------------------------------------------*/
860/*---------------------------------------------------------------------------*/
861
862ApplicationBuildInfo& ArcaneMain::
863_applicationBuildInfo()
864{
865 return m_p->m_application_build_info;
866}
867
868/*---------------------------------------------------------------------------*/
869/*---------------------------------------------------------------------------*/
870
873{
874 return m_p->m_dotnet_info;
875}
876
877/*---------------------------------------------------------------------------*/
878/*---------------------------------------------------------------------------*/
879
882{
883 return m_p->m_accelerator_info;
884}
885
886/*---------------------------------------------------------------------------*/
887/*---------------------------------------------------------------------------*/
888
891{
892 return _staticInfo()->m_init_time_accelerator;
893}
894
895/*---------------------------------------------------------------------------*/
896/*---------------------------------------------------------------------------*/
897
900{
901 _checkHasInit();
902
904 if (!factory) {
905 factory = m_default_main_factory;
906 if (!factory) {
907 factory = new ArcaneBatchMainFactory();
908 default_factory = factory;
909 }
910 }
911
912 int ret = _arcaneMain(app_info, factory);
913
914 default_factory = nullptr;
915
916 // Le code d'erreur 5 représente une erreur en parallèle pour tous les
917 // processeurs.
918 if (ret != 0 && ret != 5)
919 cerr << "* Process return: " << ret << '\n';
920 if (ret == 5)
921 ret = 4;
922
923 return ret;
924}
925
926/*---------------------------------------------------------------------------*/
927/*---------------------------------------------------------------------------*/
928
929int ArcaneMain::
931{
932 _staticInfo()->m_direct_exec_functor = func;
933 return run();
934}
935
936/*---------------------------------------------------------------------------*/
937/*---------------------------------------------------------------------------*/
938
939int ArcaneMain::
940_checkTestLoggerResult()
941{
942 if (!m_is_use_test_logger)
943 return 0;
944 if (!m_is_master_io)
945 return 0;
946 return TestLogger::compare();
947}
948
949/*---------------------------------------------------------------------------*/
950/*---------------------------------------------------------------------------*/
951
952int ArcaneMain::
953_initRuntimes()
954{
955 ArcaneMainAutoDetectRuntimeHelper auto_detect_helper;
956 return auto_detect_helper.check();
957}
958
959/*---------------------------------------------------------------------------*/
960/*---------------------------------------------------------------------------*/
961
963run()
964{
965 int r = _initRuntimes();
966 if (r != 0)
967 return r;
968
970
971 // Si on arrive ici et que le runtime C# est déjà chargé
972 // (parce que le Main est en C# par exemple), on ne lance pas le wrapper
974 if (!is_in_dotnet && dotnet_info.isUsingDotNetRuntime()) {
975 r = _runDotNet();
976 // Avant la version 3.7.8 on n'appelait par arcaneFinalize() car cela pouvait
977 // poser des problèmes avec le Garbage Collector de '.Net'. Normalement ces
978 // problèmes sont corrigés mais on autorise le comportement d'avant au cas où.
979 bool do_finalize = false;
980 String x = platform::getEnvironmentVariable("ARCANE_DOTNET_USE_LEGACY_DESTROY");
981 if (x == "1")
982 do_finalize = false;
983 if (x == "0")
984 do_finalize = true;
985 if (do_finalize)
987 }
988 else {
990 r = arcaneMain(defaultApplicationInfo(), nullptr);
992 }
993 if (r != 0)
994 return r;
995 return _checkTestLoggerResult();
996}
997
998/*---------------------------------------------------------------------------*/
999/*---------------------------------------------------------------------------*/
1000
1001int ArcaneMain::
1002_runDotNet()
1003{
1004 auto si = _staticInfo();
1005 si->m_has_dotnet_wrapper = true;
1006
1007 // TODO: vérifier que l'init n'a pas été faite.
1008
1009 // Pour pouvoir exécuter le code .Net, il faut
1010 // appeler la méthode 'arcane_mono_main' qui se trouve
1011 // dans la bibliothèque dynamique 'arcane_mono'.
1012
1014
1017
1018 DotNetMainFunctor my_functor = nullptr;
1019 String os_dir(si->m_arcane_lib_path);
1020
1021 try {
1022 _checkCreateDynamicLibraryLoader();
1023
1025 if (!dll_loader)
1026 ARCANE_FATAL("No dynamic library available for running .Net");
1027
1028 String dll_name = "arcane_mono";
1029 String symbol_name = "arcane_mono_main2";
1030
1031 String runtime_name = dotnet_info.embeddedRuntime();
1032
1033 if (runtime_name.null() || runtime_name == "mono")
1034 // Mono est le défaut si rien n'est spécifié.
1035 ;
1036 else if (runtime_name == "coreclr") {
1037 dll_name = "arcane_dotnet_coreclr";
1038 symbol_name = "arcane_dotnet_coreclr_main";
1039 }
1040 else
1041 ARCANE_FATAL("Unknown '.Net' runtime '{0}'. Valid values are 'mono' or 'coreclr'", runtime_name);
1042
1043 IDynamicLibrary* dl = dll_loader->open(os_dir, dll_name);
1044 if (!dl)
1045 ARCANE_FATAL("Can not found dynamic library '{0}' for using .Net", dll_name);
1046
1047 bool is_found = false;
1048 void* functor_addr = dl->getSymbolAddress(symbol_name, &is_found);
1049 if (!is_found)
1050 ARCANE_FATAL("Can not find symbol '{0}' in library '{1}'", symbol_name, dll_name);
1051
1052 my_functor = reinterpret_cast<DotNetMainFunctor>(functor_addr);
1053 }
1054 catch (const Exception& ex) {
1055 return arcanePrintArcaneException(ex, nullptr);
1056 }
1057 catch (const std::exception& ex) {
1058 return arcanePrintStdException(ex, nullptr);
1059 }
1060 catch (...) {
1061 return arcanePrintAnyException(nullptr);
1062 }
1063
1064 if (my_functor) {
1065 const CommandLineArguments& cmd_args = app_info.commandLineArguments();
1066 // TODO: vérifier que l'assembly 'Arcane.Main.dll' existe bien.
1067 String new_name = os_dir + "/Arcane.Main.dll";
1068 return (*my_functor)(cmd_args, new_name);
1069 }
1070 return (-1);
1071}
1072
1073/*---------------------------------------------------------------------------*/
1074/*---------------------------------------------------------------------------*/
1075// Ne pas appeler directement mais passer par ArcaneMainAutoDetectHelper.
1076void ArcaneMain::
1077_checkAutoDetectMPI()
1078{
1079 // N'active pas MPI si on utilise le service de parallélisme 'Sequential'
1080 String mp_service = defaultApplicationInfo().commandLineArguments().getParameter("MessagePassingService");
1081 if (mp_service=="Sequential")
1082 return;
1083
1084 auto si = _staticInfo();
1085 // Pour pouvoir automatiquement enregisrer MPI, il faut
1086 // appeler la méthode 'arcaneAutoDetectMessagePassingServiceMPI' qui se trouve
1087 // dans la bibliothèque dynamique 'arcane_mpi'.
1088
1089 typedef void (*ArcaneAutoDetectMPIFunctor)();
1090
1091 _checkCreateDynamicLibraryLoader();
1092
1093 IDynamicLibraryLoader* dll_loader = platform::getDynamicLibraryLoader();
1094 if (!dll_loader)
1095 return;
1096
1097 String os_dir(si->m_arcane_lib_path);
1098 String dll_name = "arcane_mpi";
1099 String symbol_name = "arcaneAutoDetectMessagePassingServiceMPI";
1100 IDynamicLibrary* dl = dll_loader->open(os_dir, dll_name);
1101 if (!dl)
1102 return;
1103
1104 bool is_found = false;
1105 void* functor_addr = dl->getSymbolAddress(symbol_name, &is_found);
1106 if (!is_found)
1107 return;
1108
1109 auto my_functor = reinterpret_cast<ArcaneAutoDetectMPIFunctor>(functor_addr);
1110 if (my_functor)
1111 (*my_functor)();
1112}
1113
1114/*---------------------------------------------------------------------------*/
1115/*---------------------------------------------------------------------------*/
1128{
1129 has_accelerator = false;
1131#if defined(ARCANE_ACCELERATOR_RUNTIME)
1133#endif
1134 auto si = _staticInfo();
1135 AcceleratorRuntimeInitialisationInfo& init_info = si->m_accelerator_init_info;
1136 if (!init_info.isUsingAcceleratorRuntime())
1137 return 0;
1138 String runtime_name = init_info.acceleratorRuntime();
1139 if (runtime_name == "sequential")
1140 return 0;
1141 if (runtime_name.empty())
1143 if (runtime_name.empty())
1144 return 0;
1145 init_info.setAcceleratorRuntime(runtime_name);
1146 try {
1147 // Pour l'instant, seuls les runtimes 'cuda', 'hip' et 'sycl' sont autorisés
1148 if (runtime_name != "cuda" && runtime_name != "hip" && runtime_name != "sycl")
1149 ARCANE_FATAL("Invalid accelerator runtime '{0}'. Only 'cuda', 'hip' or 'sycl' is allowed", runtime_name);
1150
1151 // Pour pouvoir automatiquement enregistrer un runtime accélérateur de nom \a NAME,
1152 // il faut appeler la méthode 'arcaneRegisterAcceleratorRuntime${NAME}' qui se trouve
1153 // dans la bibliothèque dynamique 'arcane_${NAME}'.
1154
1156
1157 _checkCreateDynamicLibraryLoader();
1158
1160 if (!dll_loader)
1161 ARCANE_FATAL("No dynamic library available for running accelerator runtime");
1162
1163 String os_dir(si->m_arcane_lib_path);
1164 String dll_name = "arcane_accelerator_" + runtime_name + "_runtime";
1165 String symbol_name = "arcaneRegisterAcceleratorRuntime" + runtime_name;
1167 if (!dl)
1168 ARCANE_FATAL("Can not found dynamic library '{0}' for using accelerator runtime", dll_name);
1169
1170 bool is_found = false;
1171 void* functor_addr = dl->getSymbolAddress(symbol_name, &is_found);
1172 if (!is_found || !functor_addr)
1173 ARCANE_FATAL("Can not find symbol '{0}' in library '{1}'", symbol_name, dll_name);
1174
1177
1178 String verbose_str = Arcane::platform::getEnvironmentVariable("ARCANE_DEBUG_ACCELERATOR");
1179 if (!verbose_str.null())
1180 runtime_info.setVerbose(true);
1181
1182 // Par défaut utilise la mémoire unifiée pour les données.
1183 // Le runtime accélérateur pourra changer cela.
1184 MemoryUtils::setDefaultDataMemoryResource(eMemoryResource::UnifiedMemory);
1185
1186 (*my_functor)(runtime_info);
1187 has_accelerator = true;
1188
1189 // Permet de surcharger le choix de l'allocateur des données
1190 String data_allocator_str = Arcane::platform::getEnvironmentVariable("ARCANE_DEFAULT_DATA_MEMORY_RESOURCE");
1191 if (!data_allocator_str.null()){
1193 if (v!=eMemoryResource::Unknown)
1195 }
1196 }
1197 catch (const Exception& ex) {
1198 return arcanePrintArcaneException(ex, nullptr);
1199 }
1200 catch (const std::exception& ex) {
1201 return arcanePrintStdException(ex, nullptr);
1202 }
1203 catch (...) {
1204 return arcanePrintAnyException(nullptr);
1205 }
1206 return 0;
1207}
1208
1209/*---------------------------------------------------------------------------*/
1210/*---------------------------------------------------------------------------*/
1211
1212/*---------------------------------------------------------------------------*/
1213/*---------------------------------------------------------------------------*/
1214
1215IMainFactory* ArcaneMain::m_default_main_factory = nullptr;
1216ArcaneMainExecutionOverrideFunctor* ArcaneMain::m_exec_override_functor = nullptr;
1217
1218/*---------------------------------------------------------------------------*/
1219/*---------------------------------------------------------------------------*/
1220
1221ArcaneMain::
1222ArcaneMain(const ApplicationInfo& app_info, IMainFactory* factory)
1223: m_p(new Impl(app_info))
1224, m_main_factory(factory)
1225{
1226}
1227
1228/*---------------------------------------------------------------------------*/
1229/*---------------------------------------------------------------------------*/
1230
1231ArcaneMain::
1232ArcaneMain(const ApplicationInfo& app_info, IMainFactory* factory,
1233 const ApplicationBuildInfo& app_build_info,
1234 const DotNetRuntimeInitialisationInfo& dotnet_info,
1235 const AcceleratorRuntimeInitialisationInfo& accelerator_info)
1236: m_p(new Impl(app_info, app_build_info, dotnet_info, accelerator_info))
1237, m_main_factory(factory)
1238{
1239}
1240
1241/*---------------------------------------------------------------------------*/
1242/*---------------------------------------------------------------------------*/
1243
1244ArcaneMain::
1245~ArcaneMain()
1246{
1247 // S'assure qu'on retire les observateurs associés au TheadBindingMng
1248 // avant la finalisation pour éviter de punaiser les threads alors que
1249 // cela ne sert plus à rien.
1250 m_p->m_thread_binding_mng.finalize();
1251 delete m_application;
1252 delete m_p;
1253}
1254
1255/*---------------------------------------------------------------------------*/
1256/*---------------------------------------------------------------------------*/
1257
1258/*---------------------------------------------------------------------------*/
1259/*---------------------------------------------------------------------------*/
1260
1262build()
1263{
1264 _parseApplicationBuildInfoArgs();
1265 m_application = m_main_factory->createApplication(this);
1266 m_p->m_thread_binding_mng.initialize(m_application->traceMng(),
1267 m_p->m_application_build_info.threadBindingStrategy());
1268}
1269
1270/*---------------------------------------------------------------------------*/
1271/*---------------------------------------------------------------------------*/
1272
1274applicationInfo() const
1275{
1276 return m_p->m_app_info;
1277}
1278
1279/*---------------------------------------------------------------------------*/
1280/*---------------------------------------------------------------------------*/
1281
1282void ArcaneMain::
1283_parseApplicationBuildInfoArgs()
1284{
1285 ApplicationBuildInfo& abi = _applicationBuildInfo();
1286 abi.parseArguments(m_p->m_app_info.commandLineArguments());
1287 // Appelle les visiteurs enregistrés.
1288 {
1289 auto& x = _staticInfo()->m_application_build_info_visitors;
1290 for (IApplicationBuildInfoVisitor* v : x) {
1291 if (v)
1292 v->visit(abi);
1293 }
1294 }
1295 abi.setDefaultServices();
1296}
1297
1298/*---------------------------------------------------------------------------*/
1299/*---------------------------------------------------------------------------*/
1300
1302initialize()
1303{
1304 m_application->initialize();
1305
1307 service_loader->loadApplicationServices(m_application);
1308}
1309
1310/*---------------------------------------------------------------------------*/
1311/*---------------------------------------------------------------------------*/
1312
1315{
1316 return _staticInfo()->m_service_factory_infos;
1317}
1318
1319/*---------------------------------------------------------------------------*/
1320/*---------------------------------------------------------------------------*/
1321
1324{
1325 return _staticInfo()->m_module_factory_infos;
1326}
1327
1328/*---------------------------------------------------------------------------*/
1329/*---------------------------------------------------------------------------*/
1330
1332execute()
1333{
1334 return 0;
1335}
1336
1337/*---------------------------------------------------------------------------*/
1338/*---------------------------------------------------------------------------*/
1339
1341doAbort()
1342{
1343 ::abort();
1344}
1345
1346/*---------------------------------------------------------------------------*/
1347/*---------------------------------------------------------------------------*/
1348
1351{
1352 m_error_code = errcode;
1353 if (errcode != 0) {
1354 // Seul le proc maitre écrit le fichier sauf s'il s'agit d'un fatal car
1355 // dans ce cas n'importe quel PE peut le faire.
1356 if (ArcaneMain::m_is_master_io || errcode == 4) {
1357 String errname = "fatal_" + String::fromNumber(errcode);
1358 std::ofstream ofile(errname.localstr());
1359 ofile.close();
1360 }
1361 }
1362}
1363
1364/*---------------------------------------------------------------------------*/
1365/*---------------------------------------------------------------------------*/
1366
1369{
1370 // Si vrai, affichage des informations internes
1371 bool arcane_internal = false;
1372 // Si vrai, affichage des informations internes pour chaque boucle en temps
1373 bool arcane_all_internal = false;
1374 // Si vrai, génère un fichier contenant les infos internes du code.
1375 bool arcane_database = false;
1376 // Si vrai, affichage des informations sur les modules et services présents et une aide sommaire
1377 bool arcane_help = false;
1378
1379 String us_arcane_opt("-arcane_opt");
1380 String us_help("help");
1381 String us_arcane_internal("arcane_internal");
1382 String us_arcane_all_internal("arcane_all_internal");
1383 String us_arcane_database("arcane_database");
1384
1386 for (Integer i = 0, s = args.count(); i < s; ++i) {
1387 if (args[i].startsWith("-A")) {
1388 continue;
1389 }
1390 if (args[i] != us_arcane_opt) {
1391 unknown_args.add(args[i]);
1392 continue;
1393 }
1394 bool is_valid_opt = false;
1395 ++i;
1396 String str;
1397 if (i < s)
1398 str = args[i];
1399 if (str == us_arcane_internal) {
1400 arcane_internal = true;
1401 is_valid_opt = true;
1402 }
1403 if (str == us_arcane_all_internal) {
1404 arcane_all_internal = true;
1405 is_valid_opt = true;
1406 }
1407 if (str == us_arcane_database) {
1408 arcane_database = true;
1409 is_valid_opt = true;
1410 }
1411 if (str == us_help) {
1412 arcane_help = true;
1413 is_valid_opt = true;
1414 }
1415 if (!is_valid_opt) {
1416 // Si l'option n'est pas valide, la rajoute à la liste des options
1417 // non traitées
1419 if (!str.null())
1420 unknown_args.add(str);
1421 //trace->fatal() << "Unknown arcane option <" << str << ">\n";
1422 }
1423 }
1424
1425 bool do_stop = false;
1426 if (arcane_database) {
1428 dumper.dumpArcaneDatabase();
1429 do_stop = true;
1430 }
1431 if (arcane_internal) {
1433 dumper.dumpInternalInfos();
1434 do_stop = true;
1435 }
1436 if (arcane_all_internal) {
1438 dumper.dumpInternalAllInfos();
1439 do_stop = true;
1440 }
1441 if (arcane_help) {
1442 _dumpHelp();
1443 do_stop = true;
1444 }
1445
1446 args.clear();
1448 args.add(*i);
1449
1450 return do_stop;
1451}
1452
1453/*---------------------------------------------------------------------------*/
1454/*---------------------------------------------------------------------------*/
1455
1456void ArcaneMain::
1457_dumpHelp()
1458{
1459 // Utilise un multimap car plusieurs services peuvent avoir le même nom.
1460 typedef std::multimap<String, IServiceInfo*> ServiceList;
1462 Integer max_name_size = 0;
1463
1464 {
1465 // On veut lister par IServiceInfo. Comme il est possible qu'un service ait plusieurs
1466 // fabriques, on filtre grâce à done_set.
1467 std::set<IServiceInfo*> done_set;
1468 for (ServiceFactory2Collection::Enumerator j(application()->serviceFactories2()); ++j;) {
1469 IServiceInfo* si = (*j)->serviceInfo();
1470 if (done_set.find(si) != done_set.end()) {
1471 continue;
1472 }
1473 done_set.insert(si);
1474 const String& name = si->localName();
1475 max_name_size = math::max(max_name_size, CheckedConvert::toInteger(name.length()));
1476 service_list.insert(std::make_pair(name, si));
1477 }
1478 }
1479
1480 UniqueArray<String> module_names;
1481 for (EnumeratorT<IModuleFactoryInfo*> e = application()->moduleFactoryInfos(); ++e;) {
1482 IModuleFactoryInfo* mfi = (*e);
1483 const String& name = mfi->moduleName();
1484 max_name_size = math::max(max_name_size, CheckedConvert::toInteger(name.length()));
1485 module_names.add(name);
1486 }
1487
1488 ITraceMng* trace = application()->traceMng();
1489 trace->info() << " ";
1490 trace->info() << std::setw(max_name_size) << "Module List";
1491 trace->info() << std::setw(max_name_size) << "-------------"
1492 << "--";
1493 for (int i = 0, n = module_names.size(); i < n; ++i) {
1494 trace->info() << std::setw(max_name_size) << module_names[i];
1495 }
1496
1497 trace->info() << " ";
1498 trace->info() << std::setw(max_name_size) << "Service List";
1499 trace->info() << std::setw(max_name_size) << "--------------"
1500 << "--";
1501 for (ServiceList::const_iterator i = service_list.begin(); i != service_list.end(); ++i) {
1502 IServiceInfo* si = i->second;
1503 OStringStream oss;
1504 oss() << std::setw(max_name_size) << i->first;
1505 StringCollection interfaces = si->implementedInterfaces();
1506 if (!interfaces.empty())
1507 oss() << " Implements : ";
1508 for (EnumeratorT<String> e(interfaces.enumerator()); ++e;) {
1509 oss() << e.current() << " ";
1510 }
1511 trace->info() << oss.str();
1512 }
1513
1514 const Integer option_size = 20;
1515 trace->info() << " ";
1516 trace->info() << std::setw(max_name_size) << "Usage";
1517 trace->info() << std::setw(max_name_size) << "-------"
1518 << "--";
1519 trace->info() << application()->applicationName() << ".exe [-arcane_opt OPTION] dataset_file.arc";
1520 trace->info() << "Where OPTION is";
1521 trace->info() << std::setw(option_size) << "help"
1522 << " : this help page and abort";
1523 trace->info() << std::setw(option_size) << "arcane_internal"
1524 << " : save into a file internal Arcane informations and abort execution";
1525 trace->info() << std::setw(option_size) << "arcane_all_internal"
1526 << " : save into a file timeloop informations and abort execution";
1527 trace->info() << std::setw(option_size) << "arcane_database"
1528 << " : save internal database infos in file 'arcane_database.json'";
1529 trace->info() << std::setw(option_size) << "init_only"
1530 << " : only run initialization step";
1531 trace->info() << std::setw(option_size) << "continue"
1532 << " : continue an interrupted run";
1533 trace->info() << std::setw(option_size) << "max_iteration"
1534 << " : define maximum iteration number";
1535 trace->info() << std::setw(option_size) << "casename"
1536 << " : define case name";
1537}
1538
1539/*---------------------------------------------------------------------------*/
1540/*---------------------------------------------------------------------------*/
1546extern "C" void
1548{
1549 const char* signal_str = "Unknown";
1550 bool is_alarm = false;
1552
1553 switch (val) {
1554 case SIGSEGV:
1555 signal_str = "Segmentation Fault";
1556 break;
1557 case SIGFPE:
1558 signal_str = "Floating exception";
1559 break;
1560#ifdef SIGBUS
1561 case SIGBUS:
1562 signal_str = "Bus Error";
1563 break;
1564#endif
1565#ifdef SIGSYS
1566 case SIGSYS:
1567 signal_str = "System signal";
1568 break;
1569#endif
1570#ifdef SIGPIPE
1571 case SIGPIPE:
1572 signal_str = "Broken pipe";
1573 break;
1574#endif
1575#ifdef SIGALRM
1576 case SIGALRM:
1577 signal_str = "Sigalarm";
1578 is_alarm = true;
1579 break;
1580#endif
1581#ifdef SIGVTALRM
1582 case SIGVTALRM:
1583 signal_str = "Sigalarm(VirtualTime)";
1585 is_alarm = true;
1586 break;
1587#endif
1588 }
1589
1590 cerr << "Signal Caught !!! number=" << val << " name=" << signal_str << ".\n";
1591#ifdef ARCANE_DEBUG
1592 //arcaneDebugPause("SIGNAL");
1593#endif
1594
1595#ifndef ARCANE_OS_WIN32
1596 // Pour éviter que tous les PE écrivent le même fichier pour les SIGALRM,
1597 // seul le proc maitre le fait. Dans le cas des autres signaux, tout le monde
1598 // le fait.
1599 bool create_file = ArcaneMain::isMasterIO() || (!is_alarm);
1600 if (create_file) {
1601 // Crée le fichier 'signal_*' pour indiquer en parallèle qu'un
1602 // signal a été envoyé
1603 mode_t mode = S_IRUSR | S_IWUSR;
1604 char path[256];
1605 sprintf(path, "signal_%d", written_signal_number);
1606 path[255] = '\0';
1607 int fd = ::open(path, O_WRONLY | O_CREAT | O_TRUNC, mode);
1608 if (fd != (-1))
1609 ::close(fd);
1610 }
1611#endif
1612
1613 // Repositionne les signaux pour la prochaine fois, si le signal est
1614 // un signal qui peut être reçu plusieurs fois.
1615 arcaneRedirectSignals(arcaneSignalHandler);
1616
1617 Arcane::arcaneCallDefaultSignal(val);
1618 //::exit(val);
1619}
1620
1621/*---------------------------------------------------------------------------*/
1622/*---------------------------------------------------------------------------*/
1623
1624} // End namespace Arcane
1625
1626/*---------------------------------------------------------------------------*/
1627/*---------------------------------------------------------------------------*/
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
Fonctions de gestion mémoire et des allocateurs.
Informations pour initialiser le runtime accélérateur.
Informations pour construire une instance de IApplication.
String threadBindingStrategy() const
Stratégie pour punaiser les threads des tâches.
Informations sur une application.
const CommandLineArguments & commandLineArguments() const
Arguments de la ligne de commande.
void args(StringList &args) const
Remplit args avec les arguments de la ligne de commande.
IArcaneMain * createArcaneMain(const ApplicationInfo &app_info) override
Crée une instance de IArcaneMain.
Classe pour gérer les appels aux mécanismes d'auto-détection des runtimes (MPI,Accélérateurs).
void executeFunctor() override
Exécute la méthode associé
int initialize()
Création de l'instance 'IArcaneMain'.
const ApplicationInfo & m_app_info
ATTENTION: référence.
std::atomic< Int32 > m_nb_autodetect
Nombre de fois qu'on a lancé l'auto-détection pour MPI et les accélérateurs.
Real m_init_time_accelerator
Temps passé (en seconde) dans l'initialisation pour les accélérateurs.
Int32 m_autodetect_return_value
Code retour pour l'auto-détection.
Classe de gestion de l'exécution.
Definition ArcaneMain.h:80
static ApplicationBuildInfo & defaultApplicationBuildInfo()
Informations pour l'initialisation des accélerateurs.
static AcceleratorRuntimeInitialisationInfo & defaultAcceleratorRuntimeInitialisationInfo()
Informations pour l'initialisation des accélerateurs.
static std::atomic< Int32 > m_nb_arcane_init
Nombre de fois que arcaneInitialize() a été appelé
Definition ArcaneMain.h:353
static DotNetRuntimeInitialisationInfo & defaultDotNetRuntimeInitialisationInfo()
Informations pour l'initialisation du runtime '.Net'.
static void arcaneInitialize()
Initialise Arcane.
static void addApplicationBuildInfoVisitor(IApplicationBuildInfoVisitor *visitor)
Ajoute un visiteur pour remplir ApplicationBuildInfo.
const DotNetRuntimeInitialisationInfo & dotnetRuntimeInitialisationInfo() const override
Informations d'initialisation du runtime '.Net'.
static int _checkAutoDetectAccelerator(bool &has_accelerator)
Détecte et charge la gestion du runtime des accélérateurs.
static void arcaneFinalize()
Termine l'utilisation Arcane.
static int _arcaneMain(const ApplicationInfo &, IMainFactory *)
Point d'entrée de l'exécutable.
static Real initializationTimeForAccelerator()
Retourne le temps (en seconde) pour l'initialisation des runtimes accélérateurs pour ce processus.
const ApplicationInfo & applicationInfo() const override
Informations sur l'éxécutable.
ServiceFactoryInfoCollection registeredServiceFactoryInfos() override
Liste des fabriques de service enregistrées.
const AcceleratorRuntimeInitialisationInfo & acceleratorRuntimeInitialisationInfo() const override
Informations d'initialisation du runtime pour les accélérateurs.
static int callFunctorWithCatchedException(IFunctor *functor, IArcaneMain *amain, bool *clean_abort, bool is_print=true)
Appelle le fonctor functor en récupérant les éventuelles exceptions.
ModuleFactoryInfoCollection registeredModuleFactoryInfos() override
Liste des fabriques de module enregistrées.
void setErrorCode(int errcode) override
Positionne le code de retour.
static void setHasDotNETRuntime()
Indique que l'on tourne dans le runtime .NET.
IApplication * application() const override
Application.
Definition ArcaneMain.h:321
static void setHasGarbageCollector()
Indique que certains objets sont gérés par un ramasse-miette.
static std::atomic< Int32 > m_is_init_done
1 si init terminé, 0 sinon
Definition ArcaneMain.h:355
static int run()
Point d'entrée de l'exécutable dans Arcane.
static void addServiceFactoryInfo(IServiceFactoryInfo *factory)
Ajoute une fabrique de service.
void build() override
Construit les membres la classe. L'instance n'est pas utilisable tant que cette méthode n'a pas été a...
static ApplicationInfo & defaultApplicationInfo()
Infos par défaut de l'application.
static void setExecuteOverrideFunctor(ArcaneMainExecutionOverrideFunctor *functor)
static bool hasDotNetWrapper()
Indique si on exécute une assembly '.Net' depuis un main en C++.
const ApplicationBuildInfo & applicationBuildInfo() const override
Informations pour construire l'instance IApplication.
int execute() override
Lance l'exécution. Cette méthode ne retourne que lorsqu'on quitte le programme.
void doAbort() override
Effectue un abort.
static void setDefaultMainFactory(IMainFactory *mf)
Positionne la fabrique par défaut.
void initialize() override
Initialise l'instance. L'instance n'est pas utilisable tant que cette méthode n'a pas été appelée.
bool parseArgs(StringList args) override
Analyse les arguments.
static void addModuleFactoryInfo(IModuleFactoryInfo *factory)
Ajoute une fabrique de module.
Exception lorsqu'une erreur arithmétique survient.
void clear()
Supprime tous les éléments de la collection.
Definition Collection.h:68
Integer count() const
Nombre d'éléments de la collection.
Definition Collection.h:70
Arguments de la ligne de commande.
Informations pour l'initialisation du runtime '.Net'.
static FlexLMMng * instance()
Accès au singleton.
Interface de l'application.
virtual String applicationName() const =0
Nom de l'application.
Interface de la classe de gestion du code.
Definition IArcaneMain.h:54
virtual IApplication * application() const =0
Application.
virtual void finalize()=0
Effectue les dernières opérations avant destruction de l'instance.
virtual void initialize()=0
Initialise l'instance. L'instance n'est pas utilisable tant que cette méthode n'a pas été appelée.
virtual int execute()=0
Lance l'exécution. Cette méthode ne retourne que lorsqu'on quitte le programme.
static IArcaneMain * arcaneMain()
virtual void setErrorCode(int errcode)=0
Positionne le code de retour.
static void setArcaneMain(IArcaneMain *arcane_main)
virtual void doAbort()=0
Effectue un abort.
virtual bool parseArgs(StringList args)=0
Analyse les arguments.
virtual int errorCode() const =0
Code d'erreur de l'exécution.
virtual void build()=0
Construit les membres la classe. L'instance n'est pas utilisable tant que cette méthode n'a pas été a...
virtual ITraceMng * traceMng() const =0
Gestionnaire de traces.
virtual void initialize()=0
Initialise l'instance. L'instance n'est pas utilisable tant que cette méthode n'a pas été appelée.
Interface d'un fonctor pour exécuter du code directement après la création d'un sous-domaine sans pas...
Interface d'une chargeur dynamique de bibliothèque.
virtual IDynamicLibrary * open(const String &directory, const String &name)=0
Charge une bibliothèque dynamique.
Interface d'une bibliothèque dynamique.
Manufacture des classes d'Arcane.
virtual IApplication * createApplication(IArcaneMain *)=0
Crée une instance d'un superviseur.
virtual IServiceLoader * createServiceLoader()=0
Crée une instance du chargeur de services.
virtual IArcaneMain * createArcaneMain(const ApplicationInfo &app_info)=0
Crée une instance de IArcaneMain.
Informations sur la fabrique d'un module.
Classe abstraite du superviseur de parallélisme.
Informations sur la fabrique d'un service.
Interface des informations d'un service ou d'un module.
virtual String localName() const =0
Partie locale du nom du service.
Sorties des informations internes de Arcane.
static void _buildSharedNull()
static void _destroySharedNull()
static void _destroySingleton()
Détruit le singleton.
static ItemTypeMng * _singleton()
Instance singleton du type.
Lecteur des fichiers de maillage via la bibliothèque LIMA.
Definition Lima.cc:149
Manufacture des classes d'Arcane.
Definition MainFactory.h:53
Exception lorsqu'une erreur fatale 'parallèle' est générée.
Exception lorsqu'un signal survient.
Classe de base d'une exception.
Exception lorsqu'une erreur fatale est survenue.
virtual void executeFunctor()=0
Exécute la méthode associé
Interface du gestionnaire de traces.
virtual TraceMessage info()=0
Flot pour un message d'information.
virtual TraceMessage error()=0
Flot pour un message d'erreur.
Chaîne de caractères unicode.
bool null() const
Retourne true si la chaîne est nulle.
Definition String.cc:304
ITraceMng * traceMng() const
Gestionnaire de trace.
TraceMessage info() const
Flot pour un message d'information.
T max(const T &a, const T &b, const T &c)
Retourne le maximum de trois éléments.
Definition MathUtils.h:392
Integer toInteger(Real r)
Converti un Int64 en un Integer.
void setDefaultDataMemoryResource(eMemoryResource mem_resource)
Positionne la ressource mémoire utilisée pour l'allocateur mémoire des données.
eMemoryResource getMemoryResourceFromName(const String &name)
Retourne la ressource mémoire par son nom.
String getLoadedSharedLibraryFullPath(const String &dll_name)
Retourne le chemin complet d'une bibliothèque dynamique chargée.
IDynamicLibraryLoader * getDynamicLibraryLoader()
Service utilisé pour charger dynamiquement des bibliothèques.
void platformInitialize()
Initialisations spécifiques à une platforme.
void platformTerminate()
Routines de fin de programme spécifiques à une platforme.
void setHasDotNETRuntime(bool v)
Positionne si le code s'exécute avec le runtime .NET.
IDynamicLibraryLoader * setDynamicLibraryLoader(IDynamicLibraryLoader *idll)
Positionne le service utilisé pour charger dynamiquement des bibliothèques.
bool hasDotNETRuntime()
Vrai si le code s'exécute avec le runtime .NET.
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
Collection< String > StringCollection
Collection de chaînes de caractères.
Definition UtilsTypes.h:717
void arcaneSignalHandler(int val)
Fonction appelee lorsque le programme est interrompu par le signal 'val'.
List< IService * > ServiceList
Tableau de services.
Int32 Integer
Type représentant un entier.