Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Command line debugger enters infinite loop on Ctrl+D (end of transmission) character #50170

Closed
Tracked by #51393
lihop opened this issue Jul 4, 2021 · 3 comments · Fixed by #78111
Closed
Tracked by #51393

Command line debugger enters infinite loop on Ctrl+D (end of transmission) character #50170

lihop opened this issue Jul 4, 2021 · 3 comments · Fixed by #78111

Comments

@lihop
Copy link

lihop commented Jul 4, 2021

Godot version

3.3.2-stable

System information

NixOS 21.11

Issue description

Typing Ctrl+D at CLI debugger prompt results in an infinite loop which also starts filling the log file at .local/share/godot/app_userdata/<project>/logs/godot.log with a string of the following format (script path being project dependent):

Debugger Break, Reason: 'Breakpoint'
*Frame 0 - res://drag_drop_script.gd:4 in function 'get_drag_data'
Enter "help" for assistance.
debug> 

godot-inf-loop

Expected behavior:
I would expect Ctrl+D to exit the debugger which, on Linux atleast, is consistent with other REPLs/shells such as bash, python, node, and gdb.
At the very least, I would not expect the command line debugger to go into an infinite loop.

Steps to reproduce

  1. Open any Godot project with a runnable main scene.
  2. Start godot cli in debug mode godot -d.
  3. Type Ctrl+C to drop to debugger prompt.
  4. Type Ctrl+D.

Minimal reproduction project

No response

@lihop
Copy link
Author

lihop commented Jul 10, 2021

I did some digging and here is what I found:

Affected platforms

I cannot reproduce this issue on Windows.

On Windows, using the python repl for reference, I wasn't able to reproduce this issue in powershell or git-bash. The windows equivalent of Ctrl+D is Ctrl+Z (to exit python you can use Ctrl+Z + return). This had no effect on the command line debugger. In git-bash Ctrl+C and Ctrl+Z don't appear to work at all, either when using the command line debugger or python.

Causes

The debugger repl runs a while(true) loop that starts by calling OS::get_stdin_string() to get input from stdin:

while (true) {
OS::get_singleton()->print("debug> ");
String line = OS::get_singleton()->get_stdin_string().strip_edges();

OS::get_stdin_string() in turn calls fgets():

String OS_Unix::get_stdin_string(bool p_block) {
if (p_block) {
char buff[1024];
String ret = stdin_buf + fgets(buff, 1024, stdin);
stdin_buf = "";
return ret;
}
return "";
}

In the case of Ctrl+C, fgets() returns NULL and sets the error indicator for stdin to 1 (Interrupted system call).
In the case of Ctrl+D, fgets() returns NULL and sets the end-of-File indicator for stdin.
In both cases OS::get_stdin_string() returns empty string.

However, after encountering EOF, any subsequent calls to fgets() will immediately return NULL (without waiting for or reading any more user input), thus the command line debugger enters an infinite loop, repeating the line == "" case:

if (line == "") {
print_line("\nDebugger Break, Reason: '" + p_script->debug_get_error() + "'");
print_line("*Frame " + itos(current_frame) + " - " + p_script->debug_get_stack_level_source(current_frame) + ":" + itos(p_script->debug_get_stack_level_line(current_frame)) + " in function '" + p_script->debug_get_stack_level_function(current_frame) + "'");
print_line("Enter \"help\" for assistance.");
} else if (line == "c" || line == "continue")

Possible solutions

This patch to 3.3.2-stable (tested on linux) will cause the debugger to exit on Ctrl+D (on *nix platforms). It also changes the behavior of the debugger to exit on Ctrl+C (on *nix and presumably windows platforms) which would resolve #19775 if this is the desired behavior:

diff --git a/core/script_debugger_local.cpp b/core/script_debugger_local.cpp
index 3cc14daf4c..7ccec46033 100644
--- a/core/script_debugger_local.cpp
+++ b/core/script_debugger_local.cpp
@@ -53,7 +53,14 @@ void ScriptDebuggerLocal::debug(ScriptLanguage *p_script, bool p_can_continue, b
 	while (true) {
 
 		OS::get_singleton()->print("debug> ");
-		String line = OS::get_singleton()->get_stdin_string().strip_edges();
+		String line = OS::get_singleton()->get_stdin_string();
+
+		if (line == "") {
+			print_line("");
+			line = "quit";
+		} else {
+			line = line.strip_edges();
+		}
 
 		// Cache options
 		String variable_prefix = options["variable_prefix"];

@Xrayez
Copy link
Contributor

Xrayez commented Aug 8, 2021

I stumbled upon this as well in the past. I run tests using GitHub Actions in https://github.com/goostengine/goost/blob/2cf40249f90d198bf722002bf883f78fd93bbc72/.github/workflows/linux_builds.yml#L265-L267, and sometimes in case of script error the job keeps hanging for hours until the job finally stops. This also may produce huge logs files there, but looks like GitHub handles these kind of cases and cancels the job eventually.

@rcorre
Copy link
Contributor

rcorre commented Oct 9, 2022

This patch to 3.3.2-stable (tested on linux) will cause the debugger to exit on Ctrl+D (on *nix platforms). It also changes the behavior of the debugger to exit on Ctrl+C (on *nix and presumably windows platforms) which would resolve #19775 if this is the desired behavior:

IMHO ctrl+c currently behaves correctly (though this is debated at #19775). However, the current behavior of ctrl+d is pretty clearly wrong.
Would there be any objection to a patch just fixing ctrl+d to exit the debugger instead of loop infinitely, but leaving ctrl+c as-is?

@YeldhamDev YeldhamDev added this to the 4.1 milestone Jun 11, 2023
timothyqiu pushed a commit to timothyqiu/godot that referenced this issue Aug 8, 2023
When using the command line debugger (godot -d) on Unix systems, when
entering an EOF (ctrl+D), the debugger enters an infinite loop.

Adding a check for EOF in the debugger loop exits the debugger when EOF
is entered.

Fixes godotengine#50170.

(cherry picked from commit 4ecad8d)
akien-mga pushed a commit to akien-mga/godot that referenced this issue Aug 18, 2023
When using the command line debugger (godot -d) on Unix systems, when
entering an EOF (ctrl+D), the debugger enters an infinite loop.

Adding a check for EOF in the debugger loop exits the debugger when EOF
is entered.

Fixes godotengine#50170.

(cherry picked from commit 4ecad8d)
(cherry picked from commit d1dcea7)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants