diff options
| author | Marc André Tanner <mat@brain-dump.org> | 2015-07-17 14:38:36 +0200 |
|---|---|---|
| committer | Marc André Tanner <mat@brain-dump.org> | 2015-07-19 14:12:43 +0200 |
| commit | 0fa9885cda0778467ca5737ac888ece5ef371b3d (patch) | |
| tree | fd3ab531ec8ab1e60b9ee9a782c2c38120202d7b /vis.c | |
| parent | 8129933ca51caf788e0cd7c5fdbcb43fdc64601d (diff) | |
| download | vis-0fa9885cda0778467ca5737ac888ece5ef371b3d.tar.gz vis-0fa9885cda0778467ca5737ac888ece5ef371b3d.tar.xz | |
vis: handle file truncation more gracefully
If we use the file / virtual memory system as cache (using mmap(2))
and another process truncates the file we are editing, we have a
problem. All we can do is catch the resulting SIGBUS, close the
corresponding window and print a warning message.
To test this use:
$ dd if=/dev/zero of=TEST bs=8M count=1
$ vis TEST
:! echo TRUNCATE > TEST
Diffstat (limited to 'vis.c')
| -rw-r--r-- | vis.c | 35 |
1 files changed, 35 insertions, 0 deletions
@@ -2312,8 +2312,23 @@ static Key getkey(void) { return key; } +static void sigbus_handler(int sig, siginfo_t *siginfo, void *context) { + for (File *file = vis->files; file; file = file->next) { + if (text_sigbus(file->text, siginfo->si_addr)) + file->truncated = true; + } + vis->sigbus = true; + siglongjmp(vis->sigbus_jmpbuf, 1); +} + static void mainloop() { struct timespec idle = { .tv_nsec = 0 }, *timeout = NULL; + struct sigaction sa_sigbus; + memset(&sa_sigbus, 0, sizeof sa_sigbus); + sa_sigbus.sa_flags = SA_SIGINFO; + sa_sigbus.sa_sigaction = sigbus_handler; + if (sigaction(SIGBUS, &sa_sigbus, NULL)) + die("sigaction: %s", strerror(errno)); sigset_t emptyset, blockset; sigemptyset(&emptyset); sigemptyset(&blockset); @@ -2323,11 +2338,31 @@ static void mainloop() { editor_draw(vis); vis->running = true; + sigsetjmp(vis->sigbus_jmpbuf, 1); + while (vis->running) { fd_set fds; FD_ZERO(&fds); FD_SET(STDIN_FILENO, &fds); + if (vis->sigbus) { + char *name = NULL; + for (Win *next, *win = vis->windows; win; win = next) { + next = win->next; + if (win->file->truncated) { + free(name); + name = strdup(win->file->name); + editor_window_close(win); + } + } + if (!vis->windows) + die("WARNING: file `%s' truncated!\n", name ? name : "-"); + else + editor_info_show(vis, "WARNING: file `%s' truncated!\n", name ? name : "-"); + vis->sigbus = false; + free(name); + } + editor_update(vis); idle.tv_sec = vis->mode->idle_timeout; int r = pselect(1, &fds, NULL, NULL, timeout, &emptyset); |
