mirror of
https://github.com/neovim/neovim.git
synced 2025-09-28 05:58:33 +00:00
io: retry fgets on EINTR (#7632)
The calls to `fgets` in `src/nvim/if_cscope.c` (and elsewhere) can show communication errors to the user if a signal is delivered during its system calls. For plugins that proxy subprocess output into cscope requests, a `SIGCHLD` might *always* interfere with calls into `fgets`. To see this in a debugger, put a breakpoint on `cs_reading_emsg` and watch signals come in (with lldb, using `process handle --notify true --pass true`). Next, run a subcommand from neovim that calls through cscope when it returns. A tag picker plugin, like vim-picker and fzy, with `cscopetag` and `cscopetagorder=0` set, reproduced this reliably. The breakpoint will hit after a `SIGCHLD` is delivered, and `errno` will be set to 4, `EINTR`. The caller of `fgets` should retry when `NULL` is returned with `errno` set to `EINTR`.
This commit is contained in:
@@ -553,9 +553,15 @@ static int cs_cnt_matches(size_t idx)
|
||||
|
||||
char *buf = xmalloc(CSREAD_BUFSIZE);
|
||||
for (;; ) {
|
||||
errno = 0;
|
||||
if (!fgets(buf, CSREAD_BUFSIZE, csinfo[idx].fr_fp)) {
|
||||
if (feof(csinfo[idx].fr_fp))
|
||||
if (errno == EINTR) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (feof(csinfo[idx].fr_fp)) {
|
||||
errno = EIO;
|
||||
}
|
||||
|
||||
cs_reading_emsg(idx);
|
||||
|
||||
@@ -1381,9 +1387,16 @@ static char *cs_parse_results(size_t cnumber, char *buf, int bufsize,
|
||||
char *p;
|
||||
char *name;
|
||||
|
||||
retry:
|
||||
errno = 0;
|
||||
if (fgets(buf, bufsize, csinfo[cnumber].fr_fp) == NULL) {
|
||||
if (feof(csinfo[cnumber].fr_fp))
|
||||
if (errno == EINTR) {
|
||||
goto retry;
|
||||
}
|
||||
|
||||
if (feof(csinfo[cnumber].fr_fp)) {
|
||||
errno = EIO;
|
||||
}
|
||||
|
||||
cs_reading_emsg(cnumber);
|
||||
|
||||
|
Reference in New Issue
Block a user