mirror of
https://github.com/neovim/neovim.git
synced 2026-07-09 10:59:38 +00:00
refactor(os): deduplicate console/fd boilerplate #40509
Problem: Scattered, redundant boilerplate for Windows console/fd plumbing. Solution: - Add os_dup_cloexec() - Add os_reattach_console_stdio(). - Use os_open_conin_fd().
This commit is contained in:
@@ -556,10 +556,8 @@ uint64_t channel_from_stdio(bool rpc, CallbackReader on_output, const char **err
|
||||
// Strangely, ConPTY doesn't work if stdin and stdout are pipes. So replace
|
||||
// stdin and stdout with CONIN$ and CONOUT$, respectively.
|
||||
if (embedded_mode && os_has_conpty_working()) {
|
||||
stdin_dup_fd = os_dup(STDIN_FILENO);
|
||||
os_set_cloexec(stdin_dup_fd);
|
||||
stdout_dup_fd = os_dup(STDOUT_FILENO);
|
||||
os_set_cloexec(stdout_dup_fd);
|
||||
stdin_dup_fd = os_dup_cloexec(STDIN_FILENO);
|
||||
stdout_dup_fd = os_dup_cloexec(STDOUT_FILENO);
|
||||
// :restart spawns a replacement server that must not borrow the parent
|
||||
// Nvim process console, because that parent process will soon exit.
|
||||
const bool restart_alloc_console = os_env_exists(ENV_RESTART_ALLOC_CONSOLE, true);
|
||||
@@ -577,9 +575,7 @@ uint64_t channel_from_stdio(bool rpc, CallbackReader on_output, const char **err
|
||||
ShowWindow(GetConsoleWindow(), SW_HIDE);
|
||||
}
|
||||
}
|
||||
os_enable_ctrl_c();
|
||||
os_replace_stdin_to_conin();
|
||||
os_replace_stdout_and_stderr_to_conout();
|
||||
os_reattach_console_stdio();
|
||||
}
|
||||
#else
|
||||
if (embedded_mode) {
|
||||
|
||||
@@ -84,6 +84,10 @@
|
||||
# include <sys/file.h>
|
||||
#endif
|
||||
|
||||
#ifdef MSWIN
|
||||
# include "nvim/os/os_win_console.h"
|
||||
#endif
|
||||
|
||||
#ifdef OPEN_CHR_FILES
|
||||
# include "nvim/charset.h"
|
||||
#endif
|
||||
@@ -1696,11 +1700,8 @@ failed:
|
||||
// On Unix, use stderr for stdin, makes shell commands work.
|
||||
vim_ignored = dup(2);
|
||||
#else
|
||||
// On Windows, use the console input handle for stdin.
|
||||
HANDLE conin = CreateFile("CONIN$", GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ, (LPSECURITY_ATTRIBUTES)NULL,
|
||||
OPEN_EXISTING, 0, (HANDLE)NULL);
|
||||
vim_ignored = _open_osfhandle((intptr_t)conin, _O_RDONLY);
|
||||
// On Windows, use the console input handle (CONIN$) for stdin.
|
||||
vim_ignored = os_open_conin_fd();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -303,10 +303,7 @@ int main(int argc, char **argv)
|
||||
#ifdef MSWIN
|
||||
int startup_stderr_fd = -1;
|
||||
if (embedded_mode) {
|
||||
startup_stderr_fd = os_dup(STDERR_FILENO);
|
||||
if (startup_stderr_fd >= 0) {
|
||||
os_set_cloexec(startup_stderr_fd);
|
||||
}
|
||||
startup_stderr_fd = os_dup_cloexec(STDERR_FILENO);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -554,6 +554,20 @@ os_dup_dup:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// Duplicates file descriptor `fd` and marks the copy close-on-exec (Unix) / non-inheritable
|
||||
/// (Windows), so the duped fd is not leaked to spawned child processes.
|
||||
///
|
||||
/// @return New file descriptor, or libuv error code (< 0) if the dup failed.
|
||||
int os_dup_cloexec(const int fd)
|
||||
FUNC_ATTR_WARN_UNUSED_RESULT
|
||||
{
|
||||
int newfd = os_dup(fd);
|
||||
if (newfd >= 0) {
|
||||
os_set_cloexec(newfd);
|
||||
}
|
||||
return newfd;
|
||||
}
|
||||
|
||||
/// Open the file descriptor for stdin.
|
||||
int os_open_stdin_fd(void)
|
||||
{
|
||||
@@ -564,7 +578,7 @@ int os_open_stdin_fd(void)
|
||||
stdin_dup_fd = os_dup(STDIN_FILENO);
|
||||
#ifdef MSWIN
|
||||
// Replace the original stdin with the console input handle.
|
||||
os_replace_stdin_to_conin();
|
||||
os_redirect_stdin_to_conin();
|
||||
#endif
|
||||
}
|
||||
return stdin_dup_fd;
|
||||
|
||||
@@ -42,14 +42,14 @@ void os_clear_hwnd(void)
|
||||
hWnd = NULL;
|
||||
}
|
||||
|
||||
void os_replace_stdin_to_conin(void)
|
||||
void os_redirect_stdin_to_conin(void)
|
||||
{
|
||||
close(STDIN_FILENO);
|
||||
const int conin_fd = os_open_conin_fd();
|
||||
assert(conin_fd == STDIN_FILENO);
|
||||
}
|
||||
|
||||
void os_replace_stdout_and_stderr_to_conout(void)
|
||||
void os_redirect_stdout_stderr_to_conout(void)
|
||||
{
|
||||
const HANDLE conout_handle =
|
||||
CreateFile("CONOUT$",
|
||||
@@ -66,6 +66,16 @@ void os_replace_stdout_and_stderr_to_conout(void)
|
||||
assert(conerr_fd == STDERR_FILENO);
|
||||
}
|
||||
|
||||
/// Points this process's stdio at the current console: enables Ctrl-C handling and replaces
|
||||
/// stdin/stdout/stderr with CONIN$/CONOUT$. The caller must have already acquired a console
|
||||
/// (via AttachConsole, AllocConsole, etc.).
|
||||
void os_reattach_console_stdio(void)
|
||||
{
|
||||
os_enable_ctrl_c();
|
||||
os_redirect_stdin_to_conin();
|
||||
os_redirect_stdout_stderr_to_conout();
|
||||
}
|
||||
|
||||
/// Detach from the current console and switch stdio to a hidden private one.
|
||||
///
|
||||
/// Used when an embedded server must outlive its parent console, while keeping
|
||||
@@ -75,9 +85,7 @@ void os_swap_to_hidden_console(void)
|
||||
FreeConsole();
|
||||
AllocConsole();
|
||||
ShowWindow(GetConsoleWindow(), SW_HIDE);
|
||||
os_enable_ctrl_c();
|
||||
os_replace_stdin_to_conin();
|
||||
os_replace_stdout_and_stderr_to_conout();
|
||||
os_reattach_console_stdio();
|
||||
}
|
||||
|
||||
/// Resets Windows console icon if we got an original one on startup.
|
||||
|
||||
Reference in New Issue
Block a user