mirror of
https://github.com/tmux/tmux.git
synced 2024-12-25 02:48:47 +00:00
Sync OpenBSD patchset 313:
Fix a race condition when asking a client to take over the terminal (switching to a different poll loop): If a MSG_READY was followed very quickly by a MSG_EXIT (for example if doing "tmux new 'exit'"), both messages could be read as part of the same imsg_read in the first client poll loop. The MSG_READY would then cause a switch to the second client loop, which would immediately call poll(2) again, causing the client to hang forever waiting for an exit message that it already had. Change to call imsg_get to process any existing messages before polling.
This commit is contained in:
parent
884ebb6dab
commit
83f5581da4
23
client.c
23
client.c
@ -1,4 +1,4 @@
|
|||||||
/* $Id: client.c,v 1.69 2009-09-02 20:17:23 nicm Exp $ */
|
/* $Id: client.c,v 1.70 2009-09-03 21:06:30 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@ -156,12 +156,21 @@ int
|
|||||||
client_main(struct client_ctx *cctx)
|
client_main(struct client_ctx *cctx)
|
||||||
{
|
{
|
||||||
struct pollfd pfd;
|
struct pollfd pfd;
|
||||||
int nfds;
|
int n, nfds;
|
||||||
|
|
||||||
siginit();
|
siginit();
|
||||||
|
|
||||||
logfile("client");
|
logfile("client");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* imsg_read in the first client poll loop (before the terminal has
|
||||||
|
* been initialiased) may have read messages into the buffer after the
|
||||||
|
* MSG_READY switched to here. Process anything outstanding now so poll
|
||||||
|
* doesn't hang waiting for messages that have already arrived.
|
||||||
|
*/
|
||||||
|
if (client_msg_dispatch(cctx) != 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (sigterm)
|
if (sigterm)
|
||||||
client_write_server(cctx, MSG_EXITING, NULL, 0);
|
client_write_server(cctx, MSG_EXITING, NULL, 0);
|
||||||
@ -194,6 +203,10 @@ client_main(struct client_ctx *cctx)
|
|||||||
fatalx("socket error");
|
fatalx("socket error");
|
||||||
|
|
||||||
if (pfd.revents & POLLIN) {
|
if (pfd.revents & POLLIN) {
|
||||||
|
if ((n = imsg_read(&cctx->ibuf)) == -1 || n == 0) {
|
||||||
|
cctx->exittype = CCTX_DIED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (client_msg_dispatch(cctx) != 0)
|
if (client_msg_dispatch(cctx) != 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -206,6 +219,7 @@ client_main(struct client_ctx *cctx)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
if (sigterm) {
|
if (sigterm) {
|
||||||
printf("[terminated]\n");
|
printf("[terminated]\n");
|
||||||
return (1);
|
return (1);
|
||||||
@ -256,11 +270,6 @@ client_msg_dispatch(struct client_ctx *cctx)
|
|||||||
struct msg_print_data printdata;
|
struct msg_print_data printdata;
|
||||||
ssize_t n, datalen;
|
ssize_t n, datalen;
|
||||||
|
|
||||||
if ((n = imsg_read(&cctx->ibuf)) == -1 || n == 0) {
|
|
||||||
cctx->exittype = CCTX_DIED;
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if ((n = imsg_get(&cctx->ibuf, &imsg)) == -1)
|
if ((n = imsg_get(&cctx->ibuf, &imsg)) == -1)
|
||||||
fatalx("imsg_get failed");
|
fatalx("imsg_get failed");
|
||||||
|
Loading…
Reference in New Issue
Block a user