]> SALOME platform Git repositories - modules/gui.git/blob - src/Session/Session_ServerCheck.cxx
Salome HOME
3cb7fa8a55f377a0f7dd19ec48c33e952c365c3d
[modules/gui.git] / src / Session / Session_ServerCheck.cxx
1 // Copyright (C) 2007-2015  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 // File   : Session_ServerCheck.cxx
24 // Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com)
25 //
26 #include "Session_ServerCheck.hxx"
27
28 #include <SALOMEconfig.h>
29 #include CORBA_CLIENT_HEADER(SALOME_Session)
30 #include CORBA_CLIENT_HEADER(SALOME_Registry)
31 #include CORBA_CLIENT_HEADER(SALOMEDS)
32 #include CORBA_CLIENT_HEADER(SALOME_ModuleCatalog)
33 #include CORBA_CLIENT_HEADER(SALOME_Component)
34
35 #include "Utils_ORB_INIT.hxx"
36 #include "Utils_SINGLETON.hxx"
37 #include "SALOME_NamingService.hxx"
38 #include "Basics_Utils.hxx"
39 #include "utilities.h"
40
41 #include <QApplication> 
42 #include <QWaitCondition>
43 #include <QMutexLocker>
44 #include <QStringList>
45
46 //
47 // Default settings
48 //
49
50 /*!
51   \brief Default number of attemtps to check SALOME server.
52
53   This value can be changed by setting the CSF_RepeatServerRequest
54   environment variable. For example, to set number of check attempts
55   for each server to 1000:
56   \code
57   setenv CSF_RepeatServerRequest 1000
58   \endcode
59 */
60 const int __DEFAULT__ATTEMPTS__ = 300;
61
62 /*!
63   \brief Default delay between attempts (in microseconds).
64
65   This value can be changed by setting the CSF_DelayServerRequest
66   environment variable. For example, to set delay between attemtps
67   to check SALOME servers to 100000 (0.1 second):
68   \code
69   setenv CSF_DelayServerRequest 100000
70   \endcode
71 */
72 const int __DEFAULT__DELAY__ = 50000;
73
74 // The exception being thrown out of a destructor,
75 // that is not allowed by default in C++11.
76
77 #if __cplusplus >= 201103L
78 # define TYPE_NOEXCEPT noexcept(false)
79 #else
80 # define TYPE_NOEXCEPT
81 #endif
82
83 /*!
84   \classSession_ServerCheck::Locker
85   \brief Automatic locker/unlocker.
86   \internal
87 */
88
89 class Session_ServerCheck::Locker
90 {
91 public:
92   /*!
93     \brief Constructor. Tries to aquire lock.
94   */
95   Locker( Session_ServerCheck* sc ) 
96     : myChecker( sc )
97   {
98     myChecker->myMutex->lock();
99     myChecker->myMutex->unlock();
100   }
101   /*!
102     \brief Destructor. Wakes the calling thread and goes sleeping.
103   */
104   ~Locker() TYPE_NOEXCEPT
105   {
106     myChecker->myWC->wakeAll();
107     myChecker->usleep( myChecker->myDelay );
108   }
109 private:
110   Session_ServerCheck* myChecker;
111 };
112
113 /*!
114   \class Session_ServerCheck
115   \brief The class Session_ServerCheck is used to check SALOME
116   servers availability.
117   
118   It runs in the secondrary thread. The number of attemts to check
119   each SALOME server and the time delay between checks can be specified
120   via setting the CSF_RepeatServerRequest and CSF_DelayServerRequest
121   environment variables.
122
123   Total number of the check attempts can be retrieved via totalSteps()
124   method and current check step can be retrieved via currentStep() method.
125
126   The method currentMessage() can be used to get the information message
127   about what SALOME server is currently checked. If any error occured (some
128   server could not be found) the thread loop is stopped and error status
129   is set. Error message can be retrieved with the error() method.
130 */
131
132 /*!
133   \brief Constructor.
134   \param mutex a mutex used to serialize progress operations (splash)
135   \param wc a wait condition used in combination with \a mutex
136 */
137 Session_ServerCheck::Session_ServerCheck( QMutex* mutex, QWaitCondition* wc )
138 : QThread(),
139   myMutex( mutex ),
140   myWC( wc ),
141   myCheckCppContainer( false ),
142   myCheckPyContainer( false ),
143   myCheckSVContainer( false ),
144   myAttempts( __DEFAULT__ATTEMPTS__ ),
145   myDelay   ( __DEFAULT__DELAY__ ),
146   myCurrentStep( 0 )
147 {
148   char* cenv;
149   // try to get nb of attempts from environment variable
150   if ( ( cenv = getenv( "CSF_RepeatServerRequest" ) ) && atoi( cenv ) > 0 )
151     myAttempts = atoi( cenv );
152   // try to get delay between attempts from environment variable
153   if ( ( cenv = getenv( "CSF_DelayServerRequest" ) ) && atoi( cenv ) > 0 )
154     myDelay = atoi( cenv );
155
156   // parse command line check if it is necessary to wait SALOME containers
157   QStringList args = QApplication::arguments();
158   for ( int i = 1; i < args.count(); i++ ) {
159     myCheckCppContainer = myCheckCppContainer || args[i] == "CPP";
160     myCheckPyContainer  = myCheckPyContainer  || args[i] == "PY";
161     myCheckSVContainer  = myCheckSVContainer  || args[i] == "SUPERV";
162   }
163   
164   // start thread
165   start();
166 }
167
168 /*!
169   \brief Destructor
170 */
171 Session_ServerCheck::~Session_ServerCheck()
172 {
173   terminate();
174   while( isRunning() );
175 }
176
177 /*!
178   \brief Get current information message.
179   \return current message
180 */
181 QString Session_ServerCheck::currentMessage()
182 {
183   static QStringList messages;
184   if ( messages.isEmpty() ) {
185     messages << tr( "Waiting for naming service..." ); 
186     messages << tr( "Waiting for registry server..." );
187     messages << tr( "Waiting for study server..." );
188     messages << tr( "Waiting for module catalogue server..." );
189     messages << tr( "Waiting for session server..." );
190     messages << tr( "Waiting for C++ container..." );
191     messages << tr( "Waiting for Python container..." );
192     messages << tr( "Waiting for Supervision container..." );
193   }
194   QMutexLocker locker( &myDataMutex );
195   QString msg;
196   int idx = myCurrentStep / myAttempts;
197   if ( idx >= 0 && idx < messages.count() )
198     msg = messages[ idx ];
199   return msg;
200 }
201
202 /*!
203   \brief Get error message.
204   \return error message or null string of there was no any error
205 */
206 QString Session_ServerCheck::error()
207 {
208   QMutexLocker locker( &myDataMutex );
209   return myError;
210 }
211
212 /*!
213   \brief Get current step.
214   \return current step
215 */
216 int Session_ServerCheck::currentStep()
217 {
218   QMutexLocker locker( &myDataMutex );
219   return myCurrentStep;
220 }
221
222 /*!
223   \brief Get total number of check steps.
224   \return total number of steps
225 */
226 int Session_ServerCheck::totalSteps()
227 {
228   QMutexLocker locker( &myDataMutex );
229   int cnt = 5;                       // base servers
230   if ( myCheckCppContainer ) cnt++;  // + C++ container
231   if ( myCheckPyContainer )  cnt++;  // + Python container
232   if ( myCheckSVContainer )  cnt++;  // + supervision container
233   return cnt * myAttempts;
234 }
235
236 /*!
237   \brief Modify current step.
238   \param step new current step value
239 */
240 void Session_ServerCheck::setStep( const int step )
241 {
242   QMutexLocker locker( &myDataMutex );
243   myCurrentStep = step;
244 }
245
246 /*!
247   \brief Set error message.
248   \param msg error message
249 */
250 void Session_ServerCheck::setError( const QString& msg )
251 {
252   QMutexLocker locker( &myDataMutex );
253   myError = msg;
254 }
255
256 /*!
257   \brief Thread loop function. Performs SALOME servers check.
258 */
259 void Session_ServerCheck::run()
260 {
261   // start check servers
262   int current = 0;
263   QString error;
264
265   QStringList args = QApplication::arguments();
266   int argc = args.size();
267   std::vector<std::string> args1(argc);
268   char** argv = new char*[argc];
269   for ( int i = 0; i < argc; ++i ) {
270     args1[i] = args[i].toStdString();
271     argv[i]  = const_cast<char*>( args1[i].c_str() );
272   }
273
274   bool OK = true;
275   
276   // 1. Check naming service
277   for ( int i = 0; (i < myAttempts) && OK; i++ ) {
278     Locker locker( this );
279
280     setStep( current * myAttempts + i );
281
282     try {
283       ORB_INIT& init = *SINGLETON_<ORB_INIT>::Instance();
284       CORBA::ORB_var orb = init( argc, argv );
285       CORBA::Object_var obj = orb->resolve_initial_references( "NameService" );
286       CosNaming::NamingContext_var _root_context = CosNaming::NamingContext::_narrow( obj );
287       if ( !CORBA::is_nil( _root_context ) ) {
288         setStep( ++current * myAttempts );
289         break;
290       }
291     }
292     catch( CORBA::COMM_FAILURE& ) {
293       MESSAGE( "CORBA::COMM_FAILURE: unable to contact the naming service" );
294     }
295     catch( ... ) {
296       MESSAGE( "Unknown Exception: unable to contact the naming service" );
297     }
298
299     if ( i == myAttempts-1 ) {
300       setError( tr( "Unable to contact the naming service.\n" ) );
301       OK = false;
302       //return;
303     }
304   }
305
306   // 2. Check registry server
307   for ( int i = 0; (i < myAttempts) && OK ; i++ ) {
308     Locker locker( this );
309
310     setStep( current * myAttempts + i );
311
312     try {
313       CORBA::ORB_var orb = CORBA::ORB_init( argc, argv );
314       SALOME_NamingService &NS = *SINGLETON_<SALOME_NamingService>::Instance();
315       ASSERT( SINGLETON_<SALOME_NamingService>::IsAlreadyExisting() );
316       NS.init_orb( orb );
317       CORBA::Object_var obj = NS.Resolve( "/Registry" );
318       Registry::Components_var registry = Registry::Components::_narrow( obj );
319       if ( !CORBA::is_nil( registry ) ) {
320         MESSAGE( "/Registry is found" );
321         registry->ping();
322         MESSAGE( "Registry was activated" );
323         setStep( ++current * myAttempts );
324         break;
325       }
326     }
327     catch ( ServiceUnreachable& ) {
328       MESSAGE( "Caught exception: Naming Service unreachable." );
329       error = "Naming service unreachable";
330     }
331     catch ( CORBA::COMM_FAILURE& ) {
332       MESSAGE( "Caught CORBA::SystemException CommFailure." );
333       error = "Caught CORBA::SystemException CommFailure.";
334     }
335     catch ( CORBA::SystemException& ) {
336       MESSAGE( "Caught CORBA::SystemException." );
337       error = "Caught CORBA::SystemException.";
338     }
339     catch ( CORBA::Exception& ) {
340       MESSAGE( "Caught CORBA::Exception." );
341       error = "Caught CORBA::Exception.";
342     }
343     catch (...) {
344       MESSAGE( "Caught unknown exception." );
345       error = "Caught unknown exception.";
346     }
347
348     if ( i == myAttempts-1 ) {
349       setError( tr( "Registry server is not found.\n%1" ).arg ( error ) );
350       OK = false;
351       //return;
352     }
353   }
354
355   // 3. Check data server
356   for ( int i = 0; (i < myAttempts) && OK ; i++ ) {
357     Locker locker( this );
358
359     setStep( current * myAttempts + i );
360
361     try {
362       CORBA::ORB_var orb = CORBA::ORB_init( argc, argv );
363       SALOME_NamingService &NS = *SINGLETON_<SALOME_NamingService>::Instance();
364       ASSERT( SINGLETON_<SALOME_NamingService>::IsAlreadyExisting() );
365       NS.init_orb( orb );
366       CORBA::Object_var obj = NS.Resolve( "/myStudyManager" );
367       SALOMEDS::StudyManager_var studyManager = SALOMEDS::StudyManager::_narrow( obj );
368       if ( !CORBA::is_nil( studyManager ) ) {
369         MESSAGE( "/myStudyManager is found" );
370         studyManager->ping();
371         MESSAGE( "StudyManager was activated" );
372         setStep( ++current * myAttempts );
373         break;
374       }
375     }
376     catch ( ServiceUnreachable& ) {
377       MESSAGE( "Caught exception: Naming Service unreachable." );
378       error = "Naming service unreachable";
379     }
380     catch ( CORBA::COMM_FAILURE& ) {
381       MESSAGE( "Caught CORBA::SystemException CommFailure." );
382       error = "Caught CORBA::SystemException CommFailure.";
383     }
384     catch ( CORBA::SystemException& ) {
385       MESSAGE( "Caught CORBA::SystemException." );
386       error = "Caught CORBA::SystemException.";
387     }
388     catch ( CORBA::Exception& ) {
389       MESSAGE( "Caught CORBA::Exception." );
390       error = "Caught CORBA::Exception.";
391     }
392     catch (...) {
393       MESSAGE( "Caught unknown exception." );
394       error = "Caught unknown exception.";
395     }
396
397     if ( i == myAttempts-1 ) {
398       setError( tr( "Study server is not found.\n%1" ).arg ( error ) );
399       OK = false;
400       //return;
401     }
402   }
403   
404   // 4. Check module catalogue server
405   for ( int i = 0; (i < myAttempts) && OK ; i++ ) {
406     Locker locker( this );
407
408     setStep( current * myAttempts + i );
409
410     try {
411       CORBA::ORB_var orb = CORBA::ORB_init( argc, argv );
412       SALOME_NamingService &NS = *SINGLETON_<SALOME_NamingService>::Instance();
413       ASSERT( SINGLETON_<SALOME_NamingService>::IsAlreadyExisting() );
414       NS.init_orb( orb );
415       CORBA::Object_var obj = NS.Resolve( "/Kernel/ModulCatalog" );
416       SALOME_ModuleCatalog::ModuleCatalog_var catalog = SALOME_ModuleCatalog::ModuleCatalog::_narrow( obj );
417       if ( !CORBA::is_nil( catalog ) ){
418         MESSAGE( "/Kernel/ModulCatalog is found" );
419         catalog->ping();
420         MESSAGE( "ModuleCatalog was activated" );
421         setStep( ++current * myAttempts );
422         break;
423       }
424     }
425     catch ( ServiceUnreachable& ) {
426       MESSAGE( "Caught exception: Naming Service unreachable." );
427       error = "Naming service unreachable";
428     }
429     catch ( CORBA::COMM_FAILURE& ) {
430       MESSAGE( "Caught CORBA::SystemException CommFailure." );
431       error = "Caught CORBA::SystemException CommFailure.";
432     }
433     catch ( CORBA::SystemException& ) {
434       MESSAGE( "Caught CORBA::SystemException." );
435       error = "Caught CORBA::SystemException.";
436     }
437     catch ( CORBA::Exception& ) {
438       MESSAGE( "Caught CORBA::Exception." );
439       error = "Caught CORBA::Exception.";
440     }
441     catch (...) {
442       MESSAGE( "Caught unknown exception." );
443       error = "Caught unknown exception.";
444     }
445
446     if ( i == myAttempts-1 ) {
447       setError( tr( "Module catalogue server is not found.\n%1" ).arg ( error ) );
448       OK = false;
449       //return;
450     }
451   }
452
453   // 5. Check data server
454   for ( int i = 0; (i < myAttempts) && OK ; i++ ) {
455     Locker locker( this );
456
457     setStep( current * myAttempts + i );
458
459     try {
460       CORBA::ORB_var orb = CORBA::ORB_init( argc, argv );
461       SALOME_NamingService &NS = *SINGLETON_<SALOME_NamingService>::Instance();
462       ASSERT( SINGLETON_<SALOME_NamingService>::IsAlreadyExisting() );
463       NS.init_orb( orb );
464       CORBA::Object_var obj = NS.Resolve( "/Kernel/Session" );
465       SALOME::Session_var session = SALOME::Session::_narrow( obj );
466       if ( !CORBA::is_nil( session ) ) {
467         MESSAGE( "/Kernel/Session is found" );
468         session->ping();
469         MESSAGE( "SALOME_Session was activated" );
470         setStep( ++current * myAttempts );
471         break;
472       }
473     }
474     catch ( ServiceUnreachable& ) {
475       MESSAGE( "Caught exception: Naming Service unreachable." );
476       error = "Naming service unreachable";
477     }
478     catch ( CORBA::COMM_FAILURE& ) {
479       MESSAGE( "Caught CORBA::SystemException CommFailure." );
480       error = "Caught CORBA::SystemException CommFailure.";
481     }
482     catch ( CORBA::SystemException& ) {
483       MESSAGE( "Caught CORBA::SystemException." );
484       error = "Caught CORBA::SystemException.";
485     }
486     catch ( CORBA::Exception& ) {
487       MESSAGE( "Caught CORBA::Exception." );
488       error = "Caught CORBA::Exception.";
489     }
490     catch (...) {
491       MESSAGE( "Caught unknown exception." );
492       error = "Caught unknown exception.";
493     }
494
495     if ( i == myAttempts-1 ) {
496       setError( tr( "Session server is not found.\n%1" ).arg ( error ) );
497       OK = false;
498       //return;
499     }
500   }
501
502   // 6. Check C++ container
503   if ( myCheckCppContainer ) {
504     for ( int i = 0; (i < myAttempts) && OK ; i++ ) {
505       Locker locker( this );
506       
507       setStep( current * myAttempts + i );
508
509       try {
510         CORBA::ORB_var orb = CORBA::ORB_init( argc, argv );
511         SALOME_NamingService &NS = *SINGLETON_<SALOME_NamingService>::Instance();
512         ASSERT( SINGLETON_<SALOME_NamingService>::IsAlreadyExisting() );
513         NS.init_orb( orb );
514         QString containerName = QString( "/Containers/%1/FactoryServer" ).arg( Kernel_Utils::GetHostname().c_str() );
515         CORBA::Object_var obj = NS.Resolve( containerName.toLatin1() );
516         Engines::Container_var FScontainer = Engines::Container::_narrow( obj );
517         if ( !CORBA::is_nil( FScontainer ) ) {
518           MESSAGE( containerName.toLatin1().constData() << " is found" );
519           FScontainer->ping();
520           MESSAGE( "FactoryServer container was activated" );
521           setStep( ++current * myAttempts );
522           break;
523         }
524       }
525       catch ( ServiceUnreachable& ) {
526         MESSAGE( "Caught exception: Naming Service unreachable." );
527         error = "Naming service unreachable";
528       }
529       catch ( CORBA::COMM_FAILURE& ) {
530         MESSAGE( "Caught CORBA::SystemException CommFailure." );
531         error = "Caught CORBA::SystemException CommFailure.";
532       }
533       catch ( CORBA::SystemException& ) {
534         MESSAGE( "Caught CORBA::SystemException." );
535         error = "Caught CORBA::SystemException.";
536       }
537       catch ( CORBA::Exception& ) {
538         MESSAGE( "Caught CORBA::Exception." );
539         error = "Caught CORBA::Exception.";
540       }
541       catch (...) {
542         MESSAGE( "Caught unknown exception." );
543         error = "Caught unknown exception.";
544       }
545       
546       if ( i == myAttempts-1 ) {
547         setError( tr( "C++ container is not found.\n%1" ).arg ( error ) );
548         OK = false;
549         //return;
550       }
551     }
552   }
553
554   // 7. Check Python container
555   if ( myCheckPyContainer ) {
556     for ( int i = 0; (i < myAttempts) && OK ; i++ ) {
557       Locker locker( this );
558       
559       setStep( current * myAttempts + i );
560
561       try {
562         CORBA::ORB_var orb = CORBA::ORB_init( argc, argv );
563         SALOME_NamingService &NS = *SINGLETON_<SALOME_NamingService>::Instance();
564         ASSERT( SINGLETON_<SALOME_NamingService>::IsAlreadyExisting() );
565         NS.init_orb( orb );
566         QString containerName = QString( "/Containers/%1/FactoryServerPy" ).arg( Kernel_Utils::GetHostname().c_str() );
567         CORBA::Object_var obj = NS.Resolve( containerName.toLatin1() );
568         Engines::Container_var FSPcontainer = Engines::Container::_narrow( obj );
569         if ( !CORBA::is_nil( FSPcontainer ) ) {
570           MESSAGE( containerName.toLatin1().constData() << " is found" );
571           FSPcontainer->ping();
572           MESSAGE("FactoryServerPy container was activated");
573           setStep( ++current * myAttempts );
574           break;
575         }
576       }
577       catch ( ServiceUnreachable& ) {
578         MESSAGE( "Caught exception: Naming Service unreachable." );
579         error = "Naming service unreachable";
580       }
581       catch ( CORBA::COMM_FAILURE& ) {
582         MESSAGE( "Caught CORBA::SystemException CommFailure." );
583         error = "Caught CORBA::SystemException CommFailure.";
584       }
585       catch ( CORBA::SystemException& ) {
586         MESSAGE( "Caught CORBA::SystemException." );
587         error = "Caught CORBA::SystemException.";
588       }
589       catch ( CORBA::Exception& ) {
590         MESSAGE( "Caught CORBA::Exception." );
591         error = "Caught CORBA::Exception.";
592       }
593       catch (...) {
594         MESSAGE( "Caught unknown exception." );
595         error = "Caught unknown exception.";
596       }
597
598       if ( i == myAttempts-1 ) {
599         setError( tr( "Python container is not found.\n%1" ).arg ( error ) );
600         OK = false;
601         //return;
602       }
603     }
604   }
605
606   // 8. Check supervision container
607   if ( myCheckSVContainer ) {
608     for ( int i = 0; (i < myAttempts) && OK ; i++ ) {
609       Locker locker( this );
610       
611       setStep( current * myAttempts + i );
612
613       try {
614         CORBA::ORB_var orb = CORBA::ORB_init( argc, argv );
615         SALOME_NamingService &NS = *SINGLETON_<SALOME_NamingService>::Instance();
616         ASSERT( SINGLETON_<SALOME_NamingService>::IsAlreadyExisting() );
617         NS.init_orb( orb );
618         QString containerName = QString( "/Containers/%1/SuperVisionContainer" ).arg( Kernel_Utils::GetHostname().c_str() );
619         CORBA::Object_var obj = NS.Resolve( containerName.toLatin1() );
620         Engines::Container_var SVcontainer = Engines::Container::_narrow( obj );
621         if ( !CORBA::is_nil( SVcontainer ) ) {
622           MESSAGE( containerName.toLatin1().constData() << " is found" );
623           SVcontainer->ping();
624           MESSAGE("SuperVisionContainer container was activated");
625           setStep( ++current * myAttempts );
626           break;
627         }
628       }
629       catch ( ServiceUnreachable& ) {
630         MESSAGE( "Caught exception: Naming Service unreachable." );
631         error = "Naming service unreachable";
632       }
633       catch ( CORBA::COMM_FAILURE& ) {
634         MESSAGE( "Caught CORBA::SystemException CommFailure." );
635         error = "Caught CORBA::SystemException CommFailure.";
636       }
637       catch ( CORBA::SystemException& ) {
638         MESSAGE( "Caught CORBA::SystemException." );
639         error = "Caught CORBA::SystemException.";
640       }
641       catch ( CORBA::Exception& ) {
642         MESSAGE( "Caught CORBA::Exception." );
643         error = "Caught CORBA::Exception.";
644       }
645       catch (...) {
646         MESSAGE( "Caught unknown exception." );
647         error = "Caught unknown exception.";
648       }
649     
650       if ( i == myAttempts-1 ) {
651         setError( tr( "Supervision container is not found.\n%1" ).arg ( error ) );
652         OK = false;
653         //return;
654       }
655     }
656   }
657
658   delete [] argv;
659 }