scilabRead management 43/17643/4
Cedric Delamarre [Wed, 6 Jan 2016 15:51:44 +0000 (16:51 +0100)]
* scilabRead is only called by the console thread.
* step by step mode and mscanf does not call scilabread anymore.

https://codereview.scilab.org/#/c/17044/

Change-Id: I218f93f4d396315f6fc0c2bb294f0b1eba30f7a7

scilab/modules/ast/includes/system_env/configvariable.hxx
scilab/modules/ast/src/cpp/ast/run_SeqExp.hpp
scilab/modules/ast/src/cpp/system_env/configvariable.cpp
scilab/modules/console/includes/scilabRead.h
scilab/modules/console/src/c/cmdLine/getKey.c
scilab/modules/console/src/cpp/scilabRead.cpp
scilab/modules/core/src/c/csignal.c
scilab/modules/core/src/cpp/InitScilab.cpp
scilab/modules/fileio/sci_gateway/cpp/sci_mscanf.cpp

index 3d2bd8a..31881fa 100644 (file)
@@ -27,6 +27,7 @@
 #include <map>
 #include <string>
 #include <memory>
+#include <atomic>
 
 #include "visitor.hxx"
 
@@ -495,19 +496,18 @@ public:
 
     // string read from console by scilabRead
 private:
-    static char* m_pcConsoleReadStr;
+    static std::atomic<char*> m_pcConsoleReadStr;
 public:
     static void setConsoleReadStr(char* _pcConsoleReadStr);
     static char* getConsoleReadStr();
 
     // tell if the command return by scilabRead is a scilab command or not
 private:
-    static int m_isScilabCommand;
+    static std::atomic<int> m_isScilabCommand;
 public:
     static void setScilabCommand(int _isciCmd);
     static int isScilabCommand();
 
-
     //debugger information
     static bool m_bEnabledebug;
     static std::unique_ptr<ast::ConstVisitor> m_defaultvisitor;
index eefbf0a..5c0b89d 100644 (file)
@@ -212,18 +212,22 @@ void RunVisitorT<T>::visitprivate(const SeqExp  &e)
                 {
                     //break execution
                     SetTemporaryPrompt(SCIPROMPT_PAUSE);
+
+                    // The console thread must not parse the next console input.
                     ConfigVariable::setScilabCommand(0);
+
+                    // Get the console input filled by the console thread.
                     char* pcConsoleReadStr = ConfigVariable::getConsoleReadStr();
-                    if (pcConsoleReadStr) // exec is called from a callback
+                    ThreadManagement::SendConsoleExecDoneSignal();
+                    while (pcConsoleReadStr == NULL)
                     {
-                        ThreadManagement::SendConsoleExecDoneSignal();
-                    }
-                    else // exec is called from the console
-                    {
-                        scilabRead();
                         pcConsoleReadStr = ConfigVariable::getConsoleReadStr();
+                        ThreadManagement::SendConsoleExecDoneSignal();
                     }
 
+                    // reset flag to default value
+                    ConfigVariable::setScilabCommand(1);
+
                     if (pcConsoleReadStr && pcConsoleReadStr[0] == 'p' && pcConsoleReadStr[1] == '\0')
                     {
                         //mode pause
index 90e514f..3d13870 100644 (file)
@@ -16,6 +16,7 @@
 
 #include <vector>
 #include <list>
+
 #include "context.hxx"
 #include "configvariable.hxx"
 #include "macrofile.hxx"
@@ -1574,7 +1575,7 @@ int ConfigVariable::getExecutedFileID()
 ** string read from console by scilabRead
 ** \{
 */
-char* ConfigVariable::m_pcConsoleReadStr = NULL;
+std::atomic<char*> ConfigVariable::m_pcConsoleReadStr(nullptr);
 void ConfigVariable::setConsoleReadStr(char* _pcConsoleReadStr)
 {
     m_pcConsoleReadStr = _pcConsoleReadStr;
@@ -1583,8 +1584,7 @@ void ConfigVariable::setConsoleReadStr(char* _pcConsoleReadStr)
 char* ConfigVariable::getConsoleReadStr()
 {
     ThreadManagement::LockScilabRead();
-    char* tmp = m_pcConsoleReadStr;
-    m_pcConsoleReadStr = NULL;
+    char* tmp = m_pcConsoleReadStr.exchange(NULL);
     ThreadManagement::UnlockScilabRead();
     return tmp;
 }
@@ -1597,7 +1597,7 @@ char* ConfigVariable::getConsoleReadStr()
 ** is a scilab command or not.
 ** \{
 */
-int ConfigVariable::m_isScilabCommand = 1;
+std::atomic<int> ConfigVariable::m_isScilabCommand(1);
 void ConfigVariable::setScilabCommand(int _isciCmd)
 {
     m_isScilabCommand = _isciCmd;
@@ -1605,7 +1605,7 @@ void ConfigVariable::setScilabCommand(int _isciCmd)
 
 int ConfigVariable::isScilabCommand()
 {
-    return m_isScilabCommand;
+    return m_isScilabCommand.load();
 }
 /*
 ** \}
index 0aa3231..9a65f19 100644 (file)
@@ -25,6 +25,6 @@ typedef char* (*SCILAB_INPUT_METHOD)(void);
 CONSOLE_IMPEXP void C2F(scilabread)(char* strRead, int len);
 
 CONSOLE_IMPEXP void setScilabInputMethod(SCILAB_INPUT_METHOD reader);
-CONSOLE_IMPEXP char* scilabRead();
+CONSOLE_IMPEXP int scilabRead();
 
 #endif /* !__SCILAB_READ_H__ */
index 9b5691e..3642cf3 100644 (file)
@@ -120,7 +120,7 @@ static void caseDelOrArrowKey(wchar_t ** commandLine, unsigned int *cursorLocati
                 updateTokenInScilabHistory(commandLine);
                 break;
             }
-        //home or end key in some consoles
+            //home or end key in some consoles
         case L'H':
             begLine(cmd, cursorLocation);
             break;
@@ -232,6 +232,7 @@ static void getKey(wchar_t ** commandLine, unsigned int *cursorLocation)
     if (getTokenInteruptExecution() == DO_NOT_SEND_COMMAND)
     {
         resetCommandLine(commandLine, cursorLocation);
+        return;
     }
 
     switch (key)
index 8131f05..8ec8a12 100644 (file)
@@ -40,14 +40,15 @@ void setScilabInputMethod(SCILAB_INPUT_METHOD reader)
 
 void C2F(scilabread)(char* strRead, int len)
 {
-    char* str = scilabRead();
+    scilabRead();
+    char* str = ConfigVariable::getConsoleReadStr();
     int size = std::min(static_cast<int>(strlen(str)), len - 1);
     strncpy(strRead, str, size);
     strRead[size] = '\0';
     FREE(str);
 }
 
-char *scilabRead()
+int scilabRead()
 {
     ThreadManagement::LockScilabRead();
     if (getScilabMode() == SCILAB_STD)
@@ -81,7 +82,8 @@ char *scilabRead()
     FREE(pwstIn);
 
     ConfigVariable::setConsoleReadStr(pstTemp);
+    int isSciCmd = ConfigVariable::isScilabCommand();
     ThreadManagement::UnlockScilabRead();
 
-    return pstTemp;
+    return isSciCmd;
 }
index 0673ced..105f512 100644 (file)
 #include <wchar.h>
 #include "csignal.h"
 #include "configvariable_interface.h"
-
+#include "getKey.h"
 /* If CTRL-C was pressed. */
 void controlC_handler(int sig)
 {
+    setTokenInteruptExecution(DO_NOT_SEND_COMMAND);
     setExecutionBreak();
 }
 
index 2268695..f49d61c 100644 (file)
@@ -649,12 +649,10 @@ void* scilabReadAndStore(void* param)
             //set prompt value
             C2F(setprlev) (&pause);
 
-            ConfigVariable::setScilabCommand(1);
-            scilabRead();
-            if (ConfigVariable::isScilabCommand() == 0)
+            if (scilabRead() == 0)
             {
-                // happens when the return of scilabRead is used
-                // in other thread (ie: call mscanf in a callback)
+                // happens when the return of scilabRead must not be interpreted by Scilab.
+                // ie: mscanf, step by step execution (mode 4 or 7)
                 ThreadManagement::WaitForConsoleExecDoneSignal();
                 continue;
             }
@@ -754,11 +752,11 @@ void* scilabReadAndStore(void* param)
                 }
                 else if (commandsize > 1 && command[0] == 'p' && command[1] == ' ')
                 {
-                        std::string s("disp(");
-                        s += command + 2;
-                        s += ")";
-                        tmpCommand = os_strdup(s.data());
-                        disableDebug = true;
+                    std::string s("disp(");
+                    s += command + 2;
+                    s += ")";
+                    tmpCommand = os_strdup(s.data());
+                    disableDebug = true;
                 }
                 else if (commandsize > 6 && strncmp(command, "print ", 6) == 0)
                 {
index add35fa..4d011bd 100644 (file)
@@ -91,19 +91,21 @@ types::Function::ReturnValue sci_mscanf(types::typed_list &in, int _iRetCount, t
         }
 
         // get data
-        // mscanf is called from a callback
+        // The console thread must not parse the next console input.
         ConfigVariable::setScilabCommand(0);
+
+        // Get the console input filled by the console thread.
         char* pcConsoleReadStr = ConfigVariable::getConsoleReadStr();
-        if (pcConsoleReadStr)
-        {
-            ThreadManagement::SendConsoleExecDoneSignal();
-        }
-        else // mscanf is called from the console
+        ThreadManagement::SendConsoleExecDoneSignal();
+        while (pcConsoleReadStr == NULL)
         {
-            scilabRead();
             pcConsoleReadStr = ConfigVariable::getConsoleReadStr();
+            ThreadManagement::SendConsoleExecDoneSignal();
         }
 
+        // reset flag to default value
+        ConfigVariable::setScilabCommand(1);
+
         wcsRead = to_wide_string(pcConsoleReadStr);
         FREE(pcConsoleReadStr);
         int err = do_xxscanf(L"sscanf", (FILE *)0, wcsFormat, &args, wcsRead, &retval, buf, type);