Skip to content

Commit

Permalink
If a pane is killed, cancel reading from the file. GitHub issue 3422.
Browse files Browse the repository at this point in the history
  • Loading branch information
nicm committed Jan 6, 2023
1 parent a41a927 commit 09afc6c
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 15 deletions.
3 changes: 3 additions & 0 deletions client.c
Original file line number Diff line number Diff line change
Expand Up @@ -693,6 +693,9 @@ client_dispatch_wait(struct imsg *imsg)
!(client_flags & CLIENT_CONTROL), client_file_check_cb,
NULL);
break;
case MSG_READ_CANCEL:
file_read_cancel(&client_files, imsg);
break;
case MSG_WRITE_OPEN:
file_write_open(&client_files, client_peer, imsg, 1,
!(client_flags & CLIENT_CONTROL), client_file_check_cb,
Expand Down
44 changes: 40 additions & 4 deletions file.c
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,8 @@ file_fire_done_cb(__unused int fd, __unused short events, void *arg)
struct client_file *cf = arg;
struct client *c = cf->c;

if (cf->cb != NULL && (c == NULL || (~c->flags & CLIENT_DEAD)))
if (cf->cb != NULL &&
(cf->closed || c == NULL || (~c->flags & CLIENT_DEAD)))
cf->cb(c, cf->path, cf->error, 1, cf->buffer, cf->data);
file_free(cf);
}
Expand Down Expand Up @@ -355,7 +356,7 @@ file_write(struct client *c, const char *path, int flags, const void *bdata,
}

/* Read a file. */
void
struct client_file *
file_read(struct client *c, const char *path, client_file_cb cb, void *cbdata)
{
struct client_file *cf;
Expand Down Expand Up @@ -423,10 +424,27 @@ file_read(struct client *c, const char *path, client_file_cb cb, void *cbdata)
goto done;
}
free(msg);
return;
return cf;

done:
file_fire_done(cf);
return NULL;
}

/* Cancel a file read. */
void
file_cancel(struct client_file *cf)
{
struct msg_read_cancel msg;

log_debug("read cancel file %d", cf->stream);

if (cf->closed)
return;
cf->closed = 1;

msg.stream = cf->stream;
proc_send(cf->peer, MSG_READ_CANCEL, -1, &msg, sizeof msg);
}

/* Push event, fired if there is more writing to be done. */
Expand Down Expand Up @@ -760,6 +778,24 @@ file_read_open(struct client_files *files, struct tmuxpeer *peer,
proc_send(peer, MSG_READ_DONE, -1, &reply, sizeof reply);
}

/* Handle a read cancel message (client). */
void
file_read_cancel(struct client_files *files, struct imsg *imsg)
{
struct msg_read_cancel *msg = imsg->data;
size_t msglen = imsg->hdr.len - IMSG_HEADER_SIZE;
struct client_file find, *cf;

if (msglen != sizeof *msg)
fatalx("bad MSG_READ_CANCEL size");
find.stream = msg->stream;
if ((cf = RB_FIND(client_files, files, &find)) == NULL)
fatalx("unknown stream number");
log_debug("cancel file %d", cf->stream);

file_read_error_callback(NULL, 0, cf);
}

/* Handle a write ready message (server). */
void
file_write_ready(struct client_files *files, struct imsg *imsg)
Expand Down Expand Up @@ -797,7 +833,7 @@ file_read_data(struct client_files *files, struct imsg *imsg)
return;

log_debug("file %d read %zu bytes", cf->stream, bsize);
if (cf->error == 0) {
if (cf->error == 0 && !cf->closed) {
if (evbuffer_add(cf->buffer, bdata, bsize) != 0) {
cf->error = ENOMEM;
file_fire_done(cf);
Expand Down
7 changes: 6 additions & 1 deletion tmux-protocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ enum msgtype {
MSG_WRITE_OPEN,
MSG_WRITE,
MSG_WRITE_READY,
MSG_WRITE_CLOSE
MSG_WRITE_CLOSE,
MSG_READ_CANCEL
};

/*
Expand All @@ -92,6 +93,10 @@ struct msg_read_done {
int error;
};

struct msg_read_cancel {
int stream;
};

struct msg_write_open {
int stream;
int fd;
Expand Down
5 changes: 4 additions & 1 deletion tmux.h
Original file line number Diff line number Diff line change
Expand Up @@ -2611,7 +2611,9 @@ void file_print_buffer(struct client *, void *, size_t);
void printflike(2, 3) file_error(struct client *, const char *, ...);
void file_write(struct client *, const char *, int, const void *, size_t,
client_file_cb, void *);
void file_read(struct client *, const char *, client_file_cb, void *);
struct client_file *file_read(struct client *, const char *, client_file_cb,
void *);
void file_cancel(struct client_file *);
void file_push(struct client_file *);
int file_write_left(struct client_files *);
void file_write_open(struct client_files *, struct tmuxpeer *,
Expand All @@ -2623,6 +2625,7 @@ void file_read_open(struct client_files *, struct tmuxpeer *, struct imsg *,
void file_write_ready(struct client_files *, struct imsg *);
void file_read_data(struct client_files *, struct imsg *);
void file_read_done(struct client_files *, struct imsg *);
void file_read_cancel(struct client_files *, struct imsg *);

/* server.c */
extern struct tmuxproc *server_proc;
Expand Down
16 changes: 7 additions & 9 deletions window.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ static u_int next_active_point;
struct window_pane_input_data {
struct cmdq_item *item;
u_int wp;
struct client_file *file;
};

static struct window_pane *window_pane_create(struct window *, u_int, u_int,
Expand Down Expand Up @@ -1533,18 +1534,16 @@ window_pane_input_callback(struct client *c, __unused const char *path,
size_t len = EVBUFFER_LENGTH(buffer);

wp = window_pane_find_by_id(cdata->wp);
if (wp == NULL || closed || error != 0 || (c->flags & CLIENT_DEAD)) {
if (cdata->file != NULL && (wp == NULL || c->flags & CLIENT_DEAD)) {
if (wp == NULL)
c->flags |= CLIENT_EXIT;

evbuffer_drain(buffer, len);
file_cancel(cdata->file);
} else if (cdata->file == NULL || closed || error != 0) {
cmdq_continue(cdata->item);

server_client_unref(c);
free(cdata);
return;
}
input_parse_buffer(wp, buf, len);
} else
input_parse_buffer(wp, buf, len);
evbuffer_drain(buffer, len);
}

Expand All @@ -1567,9 +1566,8 @@ window_pane_start_input(struct window_pane *wp, struct cmdq_item *item,
cdata = xmalloc(sizeof *cdata);
cdata->item = item;
cdata->wp = wp->id;

cdata->file = file_read(c, "-", window_pane_input_callback, cdata);
c->references++;
file_read(c, "-", window_pane_input_callback, cdata);

return (0);
}
Expand Down

0 comments on commit 09afc6c

Please sign in to comment.