nnn: nnn hangs on -p option with list input

nnn works as expected when piping a list of paths delimited by NUL, and works fine when using the -p - option (prints selection to stdout), but for some reason hangs indefinitely when trying to use both operations at the same time. When it hangs, my CPU heats up quite badly and it appears to be stuck in an infinite loop.

Environment details

  • Operating System: Linux arch 5.6.6-arch1-1
  • Desktop Environment: None (i3-wm)
  • Terminal Emulator: Termite
  • Shell: zsh, bash, dash
  • Custom desktop opener (if applicable):
  • Program options used: -p
  • Configuration options set:
  • Issue exists on nnn master

Exact steps to reproduce the issue

Run the following command in any directory:

find . -print0 | nnn -p -

Preview (nnn from master, compiled with O_DEBUG=1, all config variables unset, with screenkey):

gifyu

Log file: /tmp/nnndbg.

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 26 (13 by maintainers)

Commits related to this issue

Most upvoted comments

This should be fixed in master now.

Note: I did a force push to keep the changes together. Please re-fork.

@KlzXS does the following patch make sense?

@Randoragon if @KlzXS confirms, can you please test if it works as you expect?

diff --git a/src/nnn.c b/src/nnn.c
index b9bb23c..58512be 100644
--- a/src/nnn.c
+++ b/src/nnn.c
@@ -6742,9 +6742,13 @@ int main(int argc, char *argv[])
 				break;
 
 			cfg.picker = 1;
-			if (optarg[0] == '-' && optarg[1] == '\0')
+			if (optarg[0] == '-' && optarg[1] == '\0') {
 				cfg.pickraw = 1;
-			else {
+				if (!isatty(STDOUT_FILENO)) {
+					fprintf(stderr, "stdout !tty\n");
+					return _FAILURE;
+				}
+			} else {
 				int fd = open(optarg, O_WRONLY | O_CREAT, 0600);
 
 				if (fd == -1) {
@@ -6810,27 +6814,17 @@ int main(int argc, char *argv[])
 
 	atexit(cleanup);
 
-	if (!cfg.picker) {
-		/* Confirm we are in a terminal */
-		if (!isatty(STDOUT_FILENO))
-			exit(1);
-
-		/* Now we are in path list mode */
-		if (!isatty(STDIN_FILENO)) {
-			/* This is the same as listpath */
-			initpath = load_input();
-			if (!initpath)
-				exit(1);
-
-			/* We return to tty */
-			dup2(STDOUT_FILENO, STDIN_FILENO);
+	/* Check if we are in path list mode */
+	if (!isatty(STDIN_FILENO)) {
+		/* This is the same as listpath */
+		initpath = load_input();
+		if (!initpath) {
+			fprintf(stderr, "!initpath\n");
+			return _FAILURE;
 		}
-	}
 
-	/* Prevent picker and list mode conflict */
-	if (!isatty(STDIN_FILENO) || !isatty(STDOUT_FILENO)) {
-		fprintf(stderr, "stdin/out conflict\n");
-		return _FAILURE;
+		/* We return to tty */
+		dup2(STDOUT_FILENO, STDIN_FILENO);
 	}
 
 	home = getenv("HOME");