I am building an application that uses either replxx or libedit to read a line from a terminal, along with tab completion. In order for replxx and libedit to work, each library puts stdio into raw unbuffered mode so that key bindings work.
During tab completion, a tool is executed in a fashion similar to bash completion. The parent application communicates with the tool over a pipe, after a fork and an execve, and this all works fine.
There is a problem once the tool has finished execution - in the parent application, stdin has lost its raw unbuffered setting and has reverted back to line buffering. This breaks replxx and libedit, which remain frozen until enter is pressed, and then catch up with all the line buffered keypresses.
What does code need to do (or avoid doing) to fork, then execve, in such a way that stdin in the parent remains untouched?
Most specifically, does closing stdin in the child process have any kind of effect on the stdin in the parent process with respect to buffering?
The code uses Apache Portable Runtime on Linux/MacOS, and looks like this:
apr_procattr_create(&procattr, first->pool);
apr_file_pipe_create_ex(&ioread, &iowrite, APR_FULL_BLOCK,
first->pool);
apr_procattr_child_in_set(procattr, NULL, NULL);
apr_procattr_child_out_set(procattr, NULL, NULL);
apr_procattr_child_err_set(procattr, NULL, NULL);
apr_procattr_dir_set(procattr, command->r.sysconf);
apr_procattr_cmdtype_set(procattr, APR_PROGRAM);
proc = apr_pcalloc(first->pool, sizeof(apr_proc_t));
apr_proc_create(proc, command->r.libexec, (const char* const*) argv->elts,
device_environment_make(d), procattr, first->pool);
apr_file_close(proc->in);
apr_file_close(proc->err);
[do stuff that reads proc->out]
apr_file_close(proc->out);
apr_proc_wait(proc, NULL, NULL, APR_WAIT);
Current
replxxresets raw mode terminal settings after each callback returns.