diff options
| author | Paul Eggert | 2014-04-15 08:43:41 -0700 |
|---|---|---|
| committer | Paul Eggert | 2014-04-15 08:43:41 -0700 |
| commit | f5a312939f6b5105eb0a1397a831d5e67481965f (patch) | |
| tree | e44237c479e7b7f2bbeff8a75cb1cf10da4e4140 /src | |
| parent | 20fa59a004fff136c8fe8d4cd160c12d208c5cde (diff) | |
| download | emacs-f5a312939f6b5105eb0a1397a831d5e67481965f.tar.gz emacs-f5a312939f6b5105eb0a1397a831d5e67481965f.zip | |
Fix some xgselect-vs-pselect bugs.
This may not fix Bug#17172, but it fixes some bugs discovering
while auditing xgselect.c for that bug.
when one of glib's file descriptors is greater than FDS_LIM.
Treat rfds, wfds, efds consistently, and test G_IO_PRI too.
Clear input masks when pselect returns zero.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 17 | ||||
| -rw-r--r-- | src/xgselect.c | 83 |
2 files changed, 52 insertions, 48 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 51861c6ca7d..8ef5dfe9916 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,12 +1,11 @@ | |||
| 1 | 2014-04-15 Stefan Monnier <monnier@iro.umontreal.ca> | 1 | 2014-04-15 Paul Eggert <eggert@penguin.cs.ucla.edu> |
| 2 | 2 | ||
| 3 | * buffer.c (Foverlays_at): Add argument `sorted'. | 3 | Fix some xgselect-vs-pselect bugs (Bug#17172). |
| 4 | 4 | This may not fix Bug#17172, but it fixes some bugs discovering | |
| 5 | 2014-04-14 Eli Zaretskii <eliz@gnu.org> | 5 | while auditing xgselect.c for that bug. |
| 6 | 6 | when one of glib's file descriptors is greater than FDS_LIM. | |
| 7 | * insdel.c (invalidate_buffer_caches): When deleting or replacing | 7 | Treat rfds, wfds, efds consistently, and test G_IO_PRI too. |
| 8 | text, invalidate the bidi_paragraph_cache upto and including the | 8 | Clear input masks when pselect returns zero. |
| 9 | preceding newline. | ||
| 10 | 9 | ||
| 11 | 2014-04-13 Paul Eggert <eggert@cs.ucla.edu> | 10 | 2014-04-13 Paul Eggert <eggert@cs.ucla.edu> |
| 12 | 11 | ||
diff --git a/src/xgselect.c b/src/xgselect.c index 1d3f916c9f8..7decca34edf 100644 --- a/src/xgselect.c +++ b/src/xgselect.c | |||
| @@ -33,16 +33,15 @@ int | |||
| 33 | xg_select (int fds_lim, fd_set *rfds, fd_set *wfds, fd_set *efds, | 33 | xg_select (int fds_lim, fd_set *rfds, fd_set *wfds, fd_set *efds, |
| 34 | struct timespec const *timeout, sigset_t const *sigmask) | 34 | struct timespec const *timeout, sigset_t const *sigmask) |
| 35 | { | 35 | { |
| 36 | fd_set all_rfds, all_wfds; | 36 | fd_set all_rfds, all_wfds, all_efds; |
| 37 | struct timespec tmo; | 37 | struct timespec tmo; |
| 38 | struct timespec const *tmop = timeout; | 38 | struct timespec const *tmop = timeout; |
| 39 | 39 | ||
| 40 | GMainContext *context; | 40 | GMainContext *context; |
| 41 | int have_wfds = wfds != NULL; | ||
| 42 | GPollFD gfds_buf[128]; | 41 | GPollFD gfds_buf[128]; |
| 43 | GPollFD *gfds = gfds_buf; | 42 | GPollFD *gfds = gfds_buf; |
| 44 | int gfds_size = sizeof gfds_buf / sizeof *gfds_buf; | 43 | int gfds_size = sizeof gfds_buf / sizeof *gfds_buf; |
| 45 | int n_gfds, retval = 0, our_fds = 0, max_fds = fds_lim - 1; | 44 | int n_gfds, retval = 0, all_lim = fds_lim; |
| 46 | int i, nfds, tmo_in_millisec; | 45 | int i, nfds, tmo_in_millisec; |
| 47 | bool need_to_dispatch; | 46 | bool need_to_dispatch; |
| 48 | USE_SAFE_ALLOCA; | 47 | USE_SAFE_ALLOCA; |
| @@ -59,6 +58,8 @@ xg_select (int fds_lim, fd_set *rfds, fd_set *wfds, fd_set *efds, | |||
| 59 | else FD_ZERO (&all_rfds); | 58 | else FD_ZERO (&all_rfds); |
| 60 | if (wfds) all_wfds = *wfds; | 59 | if (wfds) all_wfds = *wfds; |
| 61 | else FD_ZERO (&all_wfds); | 60 | else FD_ZERO (&all_wfds); |
| 61 | if (efds) all_efds = *efds; | ||
| 62 | else FD_ZERO (&all_efds); | ||
| 62 | 63 | ||
| 63 | n_gfds = g_main_context_query (context, G_PRIORITY_LOW, &tmo_in_millisec, | 64 | n_gfds = g_main_context_query (context, G_PRIORITY_LOW, &tmo_in_millisec, |
| 64 | gfds, gfds_size); | 65 | gfds, gfds_size); |
| @@ -71,19 +72,22 @@ xg_select (int fds_lim, fd_set *rfds, fd_set *wfds, fd_set *efds, | |||
| 71 | } | 72 | } |
| 72 | 73 | ||
| 73 | for (i = 0; i < n_gfds; ++i) | 74 | for (i = 0; i < n_gfds; ++i) |
| 74 | { | 75 | if (gfds[i].events & (G_IO_IN | G_IO_OUT | G_IO_PRI)) |
| 75 | if (gfds[i].events & G_IO_IN) | 76 | { |
| 76 | { | 77 | int fd = gfds[i].fd; |
| 77 | FD_SET (gfds[i].fd, &all_rfds); | 78 | for (; all_lim <= fd; all_lim++) |
| 78 | if (gfds[i].fd > max_fds) max_fds = gfds[i].fd; | 79 | { |
| 79 | } | 80 | FD_CLR (all_lim, &all_rfds); |
| 80 | if (gfds[i].events & G_IO_OUT) | 81 | FD_CLR (all_lim, &all_wfds); |
| 81 | { | 82 | FD_CLR (all_lim, &all_efds); |
| 82 | FD_SET (gfds[i].fd, &all_wfds); | 83 | } |
| 83 | if (gfds[i].fd > max_fds) max_fds = gfds[i].fd; | 84 | if (gfds[i].events & G_IO_IN) |
| 84 | have_wfds = 1; | 85 | FD_SET (fd, &all_rfds); |
| 85 | } | 86 | if (gfds[i].events & G_IO_OUT) |
| 86 | } | 87 | FD_SET (fd, &all_wfds); |
| 88 | if (gfds[i].events & G_IO_PRI) | ||
| 89 | FD_SET (fd, &all_efds); | ||
| 90 | } | ||
| 87 | 91 | ||
| 88 | SAFE_FREE (); | 92 | SAFE_FREE (); |
| 89 | 93 | ||
| @@ -95,34 +99,35 @@ xg_select (int fds_lim, fd_set *rfds, fd_set *wfds, fd_set *efds, | |||
| 95 | tmop = &tmo; | 99 | tmop = &tmo; |
| 96 | } | 100 | } |
| 97 | 101 | ||
| 98 | fds_lim = max_fds + 1; | 102 | nfds = pselect (all_lim, &all_rfds, &all_wfds, &all_efds, tmop, sigmask); |
| 99 | nfds = pselect (fds_lim, &all_rfds, have_wfds ? &all_wfds : NULL, | ||
| 100 | efds, tmop, sigmask); | ||
| 101 | 103 | ||
| 102 | if (nfds < 0) | 104 | if (nfds < 0) |
| 103 | retval = nfds; | 105 | retval = nfds; |
| 104 | else if (nfds > 0) | 106 | else |
| 105 | { | 107 | { |
| 106 | for (i = 0; i < fds_lim; ++i) | 108 | for (i = 0; i < fds_lim; ++i) |
| 107 | { | 109 | { |
| 108 | if (FD_ISSET (i, &all_rfds)) | 110 | if (rfds && FD_ISSET (i, rfds)) |
| 109 | { | 111 | { |
| 110 | if (rfds && FD_ISSET (i, rfds)) ++retval; | 112 | if (FD_ISSET (i, &all_rfds)) |
| 111 | else ++our_fds; | 113 | retval++; |
| 112 | } | 114 | else |
| 113 | else if (rfds) | 115 | FD_CLR (i, rfds); |
| 114 | FD_CLR (i, rfds); | 116 | } |
| 115 | 117 | if (wfds && FD_ISSET (i, wfds)) | |
| 116 | if (have_wfds && FD_ISSET (i, &all_wfds)) | 118 | { |
| 117 | { | 119 | if (FD_ISSET (i, &all_wfds)) |
| 118 | if (wfds && FD_ISSET (i, wfds)) ++retval; | 120 | retval++; |
| 119 | else ++our_fds; | 121 | else |
| 120 | } | 122 | FD_CLR (i, wfds); |
| 121 | else if (wfds) | 123 | } |
| 122 | FD_CLR (i, wfds); | 124 | if (efds && FD_ISSET (i, efds)) |
| 123 | 125 | { | |
| 124 | if (efds && FD_ISSET (i, efds)) | 126 | if (FD_ISSET (i, &all_efds)) |
| 125 | ++retval; | 127 | retval++; |
| 128 | else | ||
| 129 | FD_CLR (i, efds); | ||
| 130 | } | ||
| 126 | } | 131 | } |
| 127 | } | 132 | } |
| 128 | 133 | ||
| @@ -142,7 +147,7 @@ xg_select (int fds_lim, fd_set *rfds, fd_set *wfds, fd_set *efds, | |||
| 142 | } | 147 | } |
| 143 | 148 | ||
| 144 | /* To not have to recalculate timeout, return like this. */ | 149 | /* To not have to recalculate timeout, return like this. */ |
| 145 | if ((our_fds > 0 || (nfds == 0 && tmop == &tmo)) && (retval == 0)) | 150 | if (retval == 0 && (0 < nfds || tmop == &tmo)) |
| 146 | { | 151 | { |
| 147 | retval = -1; | 152 | retval = -1; |
| 148 | errno = EINTR; | 153 | errno = EINTR; |