godot: OS.execute returns ERR_CANT_FORK

Godot version: 3.2.1

OS/device including version: Windows 10

Issue description: I need to run a batch file, which sets some env vars and launches a java applet, from inside Godot. The only way how is to use OS.execute: OS.execute("C:/build/gateway/bin/run.bat", [], false)

Contents of the .bat file:

set JAVA_HOME=c:\jdk
set PATH=%JAVA_HOME%\bin;%PATH%
set config_file="C:\build\gateway\root\conf.yaml"
set config_path="C:\build\gateway\root\"
set RUNTIME_PATH="C:\build\gateway\root\;dist\ibgroup.web.core.iblink.router.clientportal.gw.jar;build\lib\runtime\*"
java -Djava.net.preferIPv4Stack=true -Dvertx.disableDnsResolver=true -Dvertx.logger-delegate-factory-class-name=io.vertx.core.logging.SLF4JLogDelegateFactory -Dnologback.statusListenerClass=ch.qos.logback.core.status.OnConsoleStatusListener -Dnolog4j.debug=true -Dnolog4j2.debug=true -classpath %RUNTIME_PATH% ibgroup.web.core.clientportal.gw.GatewayStart

When the OS.execute method is called in an exported Godot project with debugging, the debug window throws the following error:

ERROR: execute: Condition "ret == 0" is true. Returned: ERR_CANT_FORK
   At: platform/windows/os_windows.cpp:2749

As much as I have been able to learn from searching through the archives, this error is earliest from Oct 30, 2017 and it still has not been fixed!

Here’s the kicker! When I run the run.bat manually from inside a cmd shell, it works perfectly!

I’m constructively disappointed that GDScript continues to be a flaming trainwreck.

Instead of crashing and burning like jet fuel through steel beams, the OS.execute should just figure out by itself what it needs to do to make the called program run properly like it’s been asked to.

About this issue

  • Original URL
  • State: open
  • Created 4 years ago
  • Reactions: 3
  • Comments: 22 (12 by maintainers)

Most upvoted comments

I’m sad and very disappointed that GDScript continues to be a flaming trainwreck.

I have to remind you that we have a Code of Conduct. Please stay constructive.

@Ev1lbl0w /r could be interpreted as something else than just characters in 4 places: GDScript, OS.execute, whatever API OS.execute uses, and the executed application.

  • It is not GDScript, since print("/r") does not print a carriage return (print("\r") would, though).
  • The code in OS_Windows::execute() does not do any string processing that might account for this – it just concatenates the whole command line, representing it as a string containing "command" "arg1" "arg2".
  • CreateProcessW’s documentation does not mention “escape codes” or something like that. Likewise for _wpopen
  • CMD.exe might be parsing /r as a flag, given that it is part of its first argument. Even though its documentation does not specify an /r flag, who knows what lurks in its code…

I didn’t see this mentioned anywhere in the thread: maybe Godot is interpreting /r as a carriage-return?

Great explanation @bojidar-bg! @aspenforest did you try OS.execute("CMD.exe", ["/c", "C:\\build\\gateway\\bin\\run.bat"])?

Godot uses CreateProcessW in OS::execute. The CreateProcessW documentation has the following line when explaining the parameters of CreateProcessW:

To run a batch file, you must start the command interpreter; set lpApplicationName to cmd.exe and set lpCommandLine to the following arguments: /c plus the name of the batch file. (link)

The documentation of cmd.exe also confirms the fact that the /c flag is necessary to run the command.

As Godot does not change the executable to CMD.exe or add the /c flag in any way, it is necessary to do both manually. Like this:

OS.execute("CMD.exe", ["/c", "C:\\build\\gateway\\bin\\run.bat"])

# instead of OS.execute("C:\\build\\gateway\\bin\\run.bat")

(Note: OS.execute can also use _wpopen when blocking is set to true. I’m unable to find documentation which explains how it works with batch files, however.)