mirror of https://github.com/tmux/tmux.git
If a pane is killed, cancel reading from the file. GitHub issue 3422.
This commit is contained in:
parent
a41a927441
commit
09afc6c8ee
3
client.c
3
client.c
|
@ -693,6 +693,9 @@ client_dispatch_wait(struct imsg *imsg)
|
||||||
!(client_flags & CLIENT_CONTROL), client_file_check_cb,
|
!(client_flags & CLIENT_CONTROL), client_file_check_cb,
|
||||||
NULL);
|
NULL);
|
||||||
break;
|
break;
|
||||||
|
case MSG_READ_CANCEL:
|
||||||
|
file_read_cancel(&client_files, imsg);
|
||||||
|
break;
|
||||||
case MSG_WRITE_OPEN:
|
case MSG_WRITE_OPEN:
|
||||||
file_write_open(&client_files, client_peer, imsg, 1,
|
file_write_open(&client_files, client_peer, imsg, 1,
|
||||||
!(client_flags & CLIENT_CONTROL), client_file_check_cb,
|
!(client_flags & CLIENT_CONTROL), client_file_check_cb,
|
||||||
|
|
44
file.c
44
file.c
|
@ -152,7 +152,8 @@ file_fire_done_cb(__unused int fd, __unused short events, void *arg)
|
||||||
struct client_file *cf = arg;
|
struct client_file *cf = arg;
|
||||||
struct client *c = cf->c;
|
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);
|
cf->cb(c, cf->path, cf->error, 1, cf->buffer, cf->data);
|
||||||
file_free(cf);
|
file_free(cf);
|
||||||
}
|
}
|
||||||
|
@ -355,7 +356,7 @@ done:
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read a file. */
|
/* Read a file. */
|
||||||
void
|
struct client_file *
|
||||||
file_read(struct client *c, const char *path, client_file_cb cb, void *cbdata)
|
file_read(struct client *c, const char *path, client_file_cb cb, void *cbdata)
|
||||||
{
|
{
|
||||||
struct client_file *cf;
|
struct client_file *cf;
|
||||||
|
@ -423,10 +424,27 @@ skip:
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
free(msg);
|
free(msg);
|
||||||
return;
|
return cf;
|
||||||
|
|
||||||
done:
|
done:
|
||||||
file_fire_done(cf);
|
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. */
|
/* Push event, fired if there is more writing to be done. */
|
||||||
|
@ -760,6 +778,24 @@ reply:
|
||||||
proc_send(peer, MSG_READ_DONE, -1, &reply, sizeof reply);
|
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). */
|
/* Handle a write ready message (server). */
|
||||||
void
|
void
|
||||||
file_write_ready(struct client_files *files, struct imsg *imsg)
|
file_write_ready(struct client_files *files, struct imsg *imsg)
|
||||||
|
@ -797,7 +833,7 @@ file_read_data(struct client_files *files, struct imsg *imsg)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
log_debug("file %d read %zu bytes", cf->stream, bsize);
|
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) {
|
if (evbuffer_add(cf->buffer, bdata, bsize) != 0) {
|
||||||
cf->error = ENOMEM;
|
cf->error = ENOMEM;
|
||||||
file_fire_done(cf);
|
file_fire_done(cf);
|
||||||
|
|
|
@ -66,7 +66,8 @@ enum msgtype {
|
||||||
MSG_WRITE_OPEN,
|
MSG_WRITE_OPEN,
|
||||||
MSG_WRITE,
|
MSG_WRITE,
|
||||||
MSG_WRITE_READY,
|
MSG_WRITE_READY,
|
||||||
MSG_WRITE_CLOSE
|
MSG_WRITE_CLOSE,
|
||||||
|
MSG_READ_CANCEL
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -92,6 +93,10 @@ struct msg_read_done {
|
||||||
int error;
|
int error;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct msg_read_cancel {
|
||||||
|
int stream;
|
||||||
|
};
|
||||||
|
|
||||||
struct msg_write_open {
|
struct msg_write_open {
|
||||||
int stream;
|
int stream;
|
||||||
int fd;
|
int fd;
|
||||||
|
|
5
tmux.h
5
tmux.h
|
@ -2611,7 +2611,9 @@ void file_print_buffer(struct client *, void *, size_t);
|
||||||
void printflike(2, 3) file_error(struct client *, const char *, ...);
|
void printflike(2, 3) file_error(struct client *, const char *, ...);
|
||||||
void file_write(struct client *, const char *, int, const void *, size_t,
|
void file_write(struct client *, const char *, int, const void *, size_t,
|
||||||
client_file_cb, void *);
|
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 *);
|
void file_push(struct client_file *);
|
||||||
int file_write_left(struct client_files *);
|
int file_write_left(struct client_files *);
|
||||||
void file_write_open(struct client_files *, struct tmuxpeer *,
|
void file_write_open(struct client_files *, struct tmuxpeer *,
|
||||||
|
@ -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_write_ready(struct client_files *, struct imsg *);
|
||||||
void file_read_data(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_done(struct client_files *, struct imsg *);
|
||||||
|
void file_read_cancel(struct client_files *, struct imsg *);
|
||||||
|
|
||||||
/* server.c */
|
/* server.c */
|
||||||
extern struct tmuxproc *server_proc;
|
extern struct tmuxproc *server_proc;
|
||||||
|
|
14
window.c
14
window.c
|
@ -66,6 +66,7 @@ static u_int next_active_point;
|
||||||
struct window_pane_input_data {
|
struct window_pane_input_data {
|
||||||
struct cmdq_item *item;
|
struct cmdq_item *item;
|
||||||
u_int wp;
|
u_int wp;
|
||||||
|
struct client_file *file;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct window_pane *window_pane_create(struct window *, u_int, u_int,
|
static struct window_pane *window_pane_create(struct window *, u_int, u_int,
|
||||||
|
@ -1533,17 +1534,15 @@ window_pane_input_callback(struct client *c, __unused const char *path,
|
||||||
size_t len = EVBUFFER_LENGTH(buffer);
|
size_t len = EVBUFFER_LENGTH(buffer);
|
||||||
|
|
||||||
wp = window_pane_find_by_id(cdata->wp);
|
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)
|
if (wp == NULL)
|
||||||
c->flags |= CLIENT_EXIT;
|
c->flags |= CLIENT_EXIT;
|
||||||
|
file_cancel(cdata->file);
|
||||||
evbuffer_drain(buffer, len);
|
} else if (cdata->file == NULL || closed || error != 0) {
|
||||||
cmdq_continue(cdata->item);
|
cmdq_continue(cdata->item);
|
||||||
|
|
||||||
server_client_unref(c);
|
server_client_unref(c);
|
||||||
free(cdata);
|
free(cdata);
|
||||||
return;
|
} else
|
||||||
}
|
|
||||||
input_parse_buffer(wp, buf, len);
|
input_parse_buffer(wp, buf, len);
|
||||||
evbuffer_drain(buffer, len);
|
evbuffer_drain(buffer, len);
|
||||||
}
|
}
|
||||||
|
@ -1567,9 +1566,8 @@ window_pane_start_input(struct window_pane *wp, struct cmdq_item *item,
|
||||||
cdata = xmalloc(sizeof *cdata);
|
cdata = xmalloc(sizeof *cdata);
|
||||||
cdata->item = item;
|
cdata->item = item;
|
||||||
cdata->wp = wp->id;
|
cdata->wp = wp->id;
|
||||||
|
cdata->file = file_read(c, "-", window_pane_input_callback, cdata);
|
||||||
c->references++;
|
c->references++;
|
||||||
file_read(c, "-", window_pane_input_callback, cdata);
|
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue