Quellcode durchsuchen

Ensure ctkFDHandler can be enabled/disabled multiple times

To give the opportunity to the thread to exit the polling loop, the
character "\n" is now written when disabling the handler.

The pipe is also setup each time the thread is enabled. Additionally,
the reading side of the redirection pipe is also closed when the thread is
disabled.

Tests have also been updated to enable/disable the handler multiple times
in a row.

See Slicer issue 2535
Jean-Christophe Fillion-Robin vor 12 Jahren
Ursprung
Commit
ad150902ed

+ 22 - 1
Libs/Core/Testing/Cpp/ctkErrorLogModelTest1.cpp

@@ -118,6 +118,13 @@ int ctkErrorLogModelTest1(int argc, char * argv [])
         printTextMessages(model);
         return EXIT_FAILURE;
         }
+        
+      // Check if handler can be enabled / disabled multiple times in a row
+      for (int idx = 0; idx < 3; ++idx)
+        {
+        model.setMsgHandlerEnabled(ctkErrorLogQtMessageHandler::HandlerName, false);
+        model.setMsgHandlerEnabled(ctkErrorLogQtMessageHandler::HandlerName, true);
+        }
 
       // Clear
       model.clear();
@@ -193,7 +200,14 @@ int ctkErrorLogModelTest1(int argc, char * argv [])
         printTextMessages(model);
         return EXIT_FAILURE;
         }
-
+      
+      // Check if handler can be enabled / disabled multiple times in a row
+      for (int idx = 0; idx < 3; ++idx)
+        {
+        model.setMsgHandlerEnabled(ctkErrorLogStreamMessageHandler::HandlerName, false);
+        model.setMsgHandlerEnabled(ctkErrorLogStreamMessageHandler::HandlerName, true);
+        }
+        
       // Clear
       model.clear();
 
@@ -276,6 +290,13 @@ int ctkErrorLogModelTest1(int argc, char * argv [])
         return EXIT_FAILURE;
         }
 
+      // Check if handler can be enabled / disabled multiple times in a row
+      for (int idx = 0; idx < 3; ++idx)
+        {
+        model.setMsgHandlerEnabled(ctkErrorLogFDMessageHandler::HandlerName, false);
+        model.setMsgHandlerEnabled(ctkErrorLogFDMessageHandler::HandlerName, true);
+        }
+
       // Clear
       model.clear();
 

+ 14 - 10
Libs/Core/ctkErrorLogFDMessageHandler.cpp

@@ -51,8 +51,6 @@ ctkFDHandler::ctkFDHandler(ctkErrorLogFDMessageHandler* messageHandler,
   this->TerminalOutput = terminalOutput;
   this->SavedFDNumber = 0;
   this->Enabled = false;
-  this->Initialized = false;
-  this->init();
 }
 
 // --------------------------------------------------------------------------
@@ -61,7 +59,7 @@ ctkFDHandler::~ctkFDHandler()
 }
 
 // --------------------------------------------------------------------------
-void ctkFDHandler::init()
+void ctkFDHandler::setupPipe()
 {
 #ifdef Q_OS_WIN32
   int status = _pipe(this->Pipe, 65536, _O_TEXT);
@@ -73,7 +71,6 @@ void ctkFDHandler::init()
     qCritical().nospace() << "ctkFDHandler - Failed to create pipe !";
     return;
     }
-  this->Initialized = true;
 }
 
 // --------------------------------------------------------------------------
@@ -85,10 +82,6 @@ FILE* ctkFDHandler::terminalOutputFile()
 // --------------------------------------------------------------------------
 void ctkFDHandler::setEnabled(bool value)
 {
-  if (!this->Initialized)
-    {
-    return;
-    }
   if (this->Enabled == value)
     {
     return;
@@ -96,6 +89,8 @@ void ctkFDHandler::setEnabled(bool value)
 
   if (value)
     {
+    this->setupPipe();
+
     // Flush (stdout|stderr) so that any buffered messages are delivered
     fflush(this->terminalOutputFile());
 
@@ -117,6 +112,12 @@ void ctkFDHandler::setEnabled(bool value)
     }
   else
     {
+    // Print one character to "unblock" the read function associated with the polling thread
+    ssize_t res = write(fileno(this->terminalOutputFile()), "\n", 1);
+    if (res == -1)
+      {
+      return;
+      }
     // Flush stdout or stderr so that any buffered messages are delivered
     fflush(this->terminalOutputFile());
 
@@ -147,11 +148,14 @@ void ctkFDHandler::setEnabled(bool value)
     clearerr(this->terminalOutputFile());
     fsetpos(this->terminalOutputFile(), &this->SavedFDPos);
 
+
 #ifdef Q_OS_WIN32
-    this->SavedFDNumber = _fileno(this->terminalOutputFile());
+    _close(this->Pipe[0]);
 #else
-    this->SavedFDNumber = fileno(this->terminalOutputFile());
+    close(this->Pipe[0]);
 #endif
+
+    this->SavedFDNumber = 0;
     }
 
   ctkErrorLogTerminalOutput * terminalOutput =

+ 1 - 1
Libs/Core/ctkErrorLogFDMessageHandler_p.h

@@ -59,7 +59,7 @@ public:
   FILE* terminalOutputFile();
 
 protected:
-  void init();
+  void setupPipe();
 
   void run();
 

+ 7 - 0
Libs/ImageProcessing/ITK/Core/Testing/Cpp/ctkITKErrorLogModelTest1.cpp

@@ -106,6 +106,13 @@ int ctkITKErrorLogModelTest1(int argc, char * argv [])
       return EXIT_FAILURE;
       }
 
+    // Check if handler can be enabled / disabled multiple times in a row
+    for (int idx = 0; idx < 3; ++idx)
+      {
+      model.setMsgHandlerEnabled(ctkITKErrorLogMessageHandler::HandlerName, false);
+      model.setMsgHandlerEnabled(ctkITKErrorLogMessageHandler::HandlerName, true);
+      }
+
     // Clear
     model.clear();
 

+ 7 - 0
Libs/Visualization/VTK/Core/Testing/Cpp/ctkVTKErrorLogModelTest1.cpp

@@ -97,6 +97,13 @@ int ctkVTKErrorLogModelTest1(int argc, char * argv [])
       return EXIT_FAILURE;
       }
 
+    // Check if handler can be enabled / disabled multiple times in a row
+    for (int idx = 0; idx < 3; ++idx)
+      {
+      model.setMsgHandlerEnabled(ctkVTKErrorLogMessageHandler::HandlerName, false);
+      model.setMsgHandlerEnabled(ctkVTKErrorLogMessageHandler::HandlerName, true);
+      }
+
     // Clear
     model.clear();