[flang-commits] [flang] [flang] Fix execute_command_line cmdstat is not set when error occurs (PR #93023)

Daniel Chen via flang-commits flang-commits at lists.llvm.org
Mon Jun 10 08:03:12 PDT 2024


================
@@ -64,22 +64,40 @@ void CheckAndStoreIntToDescriptor(
 // the CMDSTAT variable is not present, error termination is initiated.
 int TerminationCheck(int status, const Descriptor *cmdstat,
     const Descriptor *cmdmsg, Terminator &terminator) {
-  if (status == -1) {
-    if (!cmdstat) {
-      terminator.Crash("Execution error with system status code: %d", status);
-    } else {
-      StoreIntToDescriptor(cmdstat, EXECL_ERR, terminator);
-      CheckAndCopyCharsToDescriptor(cmdmsg, "Execution error");
-    }
-  }
 #ifdef _WIN32
   // On WIN32 API std::system returns exit status directly
   int exitStatusVal{status};
-  if (exitStatusVal == 1) {
 #else
   int exitStatusVal{WEXITSTATUS(status)};
-  if (exitStatusVal == 127 || exitStatusVal == 126) {
+  if (exitStatusVal == 1) {
+    if (!cmdstat) {
+      terminator.Crash("General Error with exit status code: 1");
+    } else {
+      StoreIntToDescriptor(cmdstat, INVALID_CL_ERR, terminator);
+      CheckAndCopyCharsToDescriptor(cmdmsg,
+          "General Error: a catch-all exit code for a variety of general "
+          "errors.");
+    }
+  } else if (exitStatusVal == 126) {
+    if (!cmdstat) {
+      terminator.Crash("Command cannot execute with exit status code: 126");
+    } else {
+      StoreIntToDescriptor(cmdstat, INVALID_CL_ERR, terminator);
+      CheckAndCopyCharsToDescriptor(cmdmsg,
+          "Command cannot execute: command was found, but it could not be "
+          "executed.");
+    }
+  } else if (exitStatusVal == 127) {
+    if (!cmdstat) {
+      terminator.Crash("Command not found with exit status code: 127");
+    } else {
+      StoreIntToDescriptor(cmdstat, INVALID_CL_ERR, terminator);
+      CheckAndCopyCharsToDescriptor(cmdmsg,
+          "Command not found: command was not found in the system's PATH");
+    }
+  } else
 #endif
+  if (exitStatusVal != 0) {
----------------
DanielCChen wrote:

Thanks for the update!
It seems to me the "old" logic is

```
if (status == -1) { //  Case 1: common for both Linux and Windows
...
}
#ifdef windows
  if (exitStatusVal == 1) { // Case 2 for all errors on windows.
#else
  if (exitStatusVal == 126 or 127 { // Case 3 (126) and Case 4 (127) for Linux.
#end if
...
}
```

I think what is missing is there is no checking for `exitStatusVal == 1` to catch the case in my issue on Linux. 
I am not sure if we need `exitStatusVal != 0` case though. 
Based on your commits, may I suggest something like:
```
enum CMD_STAT {
  ASYNC_NO_SUPPORT_ERR = -2,
  NO_SUPPORT_ERR = -1,
  CMD_EXECUTED = 0,
  FORK_ERR = 1,
  COMMAND_EXECUTION_ERR = 2, // exit code 1
  COMMAND_CANNOT_EXECUTE_ERR = 3, // Linux exit code 126
  COMMAND_NOT_FOUND_ERR = 4, // Linux exit code 127
  SIGNAL_ERR = 5
};
...

  if (status == -1) {
    if (!cmdstat) {
      terminator.Crash("Command line execution is not supported with system status code: %d.", status);
    } else {
      StoreIntToDescriptor(cmdstat, NO_SUPPORT_ERR, terminator);
      CheckAndCopyCharsToDescriptor(cmdmsg, "Command line execution is not supported.");
    }
  }
#ifdef _WIN32
  // On WIN32 API std::system returns exit status directly
  int exitStatusVal{status};
  if (exitStatusVal == 1) {
    if (!cmdstat) {
      terminator.Crash(
          "Invalid command quit with exit status code: %d.", exitStatusVal);
    } else {
      StoreIntToDescriptor(cmdstat, INVALID_CL_ERR, terminator);
      CheckAndCopyCharsToDescriptor(cmdmsg, "Invalid command line."); // Since Windows doesn't have different return code for different errors, use a generic error message.
    }
  }
#else
  int exitStatusVal{WEXITSTATUS(status)};
  if (exitStatusVal == 1) {
    if (!cmdstat) {
      terminator.Crash("Command line execution failed with exit code: 1.");
    } else {
      StoreIntToDescriptor(cmdstat, COMMAND_EXECUTION_ERR , terminator);
      CheckAndCopyCharsToDescriptor(cmdmsg,
          "Command line execution failed with exit code: 1.");
    }
  } else if (exitStatusVal == 126) {
    if (!cmdstat) {
      terminator.Crash("Command cannot be executed with exit code: 126.");
    } else {
      StoreIntToDescriptor(cmdstat, COMMAND_CANNOT_EXECUTE_ERR, terminator);
      CheckAndCopyCharsToDescriptor(cmdmsg,
          "Command cannot be executed with exit code: 126.");;
    }
  } else if (exitStatusVal == 127) {
    if (!cmdstat) {
      terminator.Crash("Command not found with exit code: 127.");
    } else {
      StoreIntToDescriptor(cmdstat, COMMAND_NOT_FOUND_ERR, terminator);
      CheckAndCopyCharsToDescriptor(cmdmsg,
          "Command not found with exit code: 127.");
    }
  }
  ```
  
  Please note that I am not sure what case `status == -1` covers. I assumed it is for the case that a processor that doesn't support command line execution, so I changed the `CMD_STAT` of it from `EXECL_ERR` to `NO_SUPPORT_ERR`. Please correct me if I am wrong. BTW, 'NO_SUPPORT_ERR` seems is not used anywhere.

https://github.com/llvm/llvm-project/pull/93023


More information about the flang-commits mailing list