Browse Source

Fix fork()/stdio_streams related errors

Serj Kalichev 2 years ago
parent
commit
12cbbf0b56
1 changed files with 17 additions and 1 deletions
  1. 17 1
      klish/ksession/kexec.c

+ 17 - 1
klish/ksession/kexec.c

@@ -281,6 +281,14 @@ static bool_t exec_action(kcontext_t *context, const kaction_t *action,
 		return BOOL_TRUE;
 	}
 
+	// Oh, it's amazing world of stdio!
+	// Flush buffers before fork() because buffer content will be inherited
+	// by child. Moreover dup2() can replace old stdout file descriptor by
+	// the new one but buffer linked with stdout stream will remain the same.
+	// It must be empty.
+	fflush(stdout);
+	fflush(stderr);
+
 	// Unsync symbol execution i.e. using forked process
 	child_pid = fork();
 	if (child_pid == -1)
@@ -300,7 +308,15 @@ static bool_t exec_action(kcontext_t *context, const kaction_t *action,
 	dup2(kcontext_stdout(context), STDOUT_FILENO);
 	dup2(kcontext_stderr(context), STDERR_FILENO);
 
-	_exit(fn(context));
+	exitcode = fn(context);
+	// We will use _exit() later so stdio streams will remain unflushed.
+	// Some output data can be lost. Flush necessary streams here.
+	fflush(stdout);
+	fflush(stderr);
+	// Use _exit() but not exit() to don't flush all the stdio streams. It
+	// can be dangerous because parent can have a lot of streams inhereted
+	// by child process.
+	_exit(exitcode);
 
 	return BOOL_TRUE;
 }