diff options
| author | Paul Eggert | 2018-11-26 08:25:36 -0800 |
|---|---|---|
| committer | Paul Eggert | 2018-11-26 11:39:44 -0800 |
| commit | 0331f2f4c5d7d9221522e231ebd5e4f20868c2b7 (patch) | |
| tree | 823516bbb6e7aa324390af1b3d1b280b5c758d6e /lib-src | |
| parent | f3328f995ee316cffa1a86117e6da2ba299d2c90 (diff) | |
| download | emacs-0331f2f4c5d7d9221522e231ebd5e4f20868c2b7.tar.gz emacs-0331f2f4c5d7d9221522e231ebd5e4f20868c2b7.zip | |
emacsclient: fix some races on POSIX systems
Fix some longstanding race conditions due to emacsclient’s use of
‘signal’ instead of ‘sigaction’ and its use of nested signal
handlers. These races could cause premature exit or incorrect
commands sent to Emacs.
* lib-src/emacsclient.c (signal) [!WINDOWSNT]: Do not undef.
(emacs_socket): Remove this static variable. It is now a parameter.
(send_to_emacs): Do not exit merely because ‘send’ was interrupted.
Instead, act on the signal if possible, and then retry the ‘send’.
(pass_signal_to_emacs): Remove; now done by act_on_signals.
(reinstall_handler_if_needed, handle_sigttou, handle_sigwinch)
(install_handler): New functions.
(got_sigcont, got_sigtstp, got_sigttou, got_sigwinch):
New globals, used for more-portable signal handling.
(handle_sigcont, handle_sigtstp): Just set the static var; other
actions are now done later by act_on_signals.
(install_handler): New function that arranges for signals to
never be reset to default, on modern POSIX platforms.
This fixes some races.
(act_on_signals): New function. When acting on SIGCONT,
don’t bother calling getpgrp if tcgetpgrp fails.
(start_daemon_and_retry_set_socket): Return the socket
rather than setting a global variable. All uses changed.
(flush_stdout): New function that acts on signals received while
flushing.
(main): Use it. emacs_socket is now a local var.
Act on signals received during recv.
Diffstat (limited to 'lib-src')
| -rw-r--r-- | lib-src/emacsclient.c | 281 |
1 files changed, 196 insertions, 85 deletions
diff --git a/lib-src/emacsclient.c b/lib-src/emacsclient.c index 3c6215a0144..d544fa63356 100644 --- a/lib-src/emacsclient.c +++ b/lib-src/emacsclient.c | |||
| @@ -41,6 +41,8 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 41 | char *w32_getenv (const char *); | 41 | char *w32_getenv (const char *); |
| 42 | # define egetenv(VAR) w32_getenv (VAR) | 42 | # define egetenv(VAR) w32_getenv (VAR) |
| 43 | 43 | ||
| 44 | # undef signal | ||
| 45 | |||
| 44 | #else /* !WINDOWSNT */ | 46 | #else /* !WINDOWSNT */ |
| 45 | 47 | ||
| 46 | # ifdef HAVE_NTGUI | 48 | # ifdef HAVE_NTGUI |
| @@ -68,8 +70,6 @@ char *w32_getenv (const char *); | |||
| 68 | 70 | ||
| 69 | #endif /* !WINDOWSNT */ | 71 | #endif /* !WINDOWSNT */ |
| 70 | 72 | ||
| 71 | #undef signal | ||
| 72 | |||
| 73 | #include <ctype.h> | 73 | #include <ctype.h> |
| 74 | #include <errno.h> | 74 | #include <errno.h> |
| 75 | #include <getopt.h> | 75 | #include <getopt.h> |
| @@ -144,7 +144,7 @@ static char const *server_file; | |||
| 144 | /* If non-NULL, the tramp prefix emacs must use to find the files. */ | 144 | /* If non-NULL, the tramp prefix emacs must use to find the files. */ |
| 145 | static char const *tramp_prefix; | 145 | static char const *tramp_prefix; |
| 146 | 146 | ||
| 147 | /* PID of the Emacs server process. */ | 147 | /* If nonzero, PID of the Emacs server process. */ |
| 148 | static pid_t emacs_pid; | 148 | static pid_t emacs_pid; |
| 149 | 149 | ||
| 150 | /* If non-NULL, a string that should form a frame parameter alist to | 150 | /* If non-NULL, a string that should form a frame parameter alist to |
| @@ -734,10 +734,13 @@ fail (void) | |||
| 734 | 734 | ||
| 735 | #if defined HAVE_SOCKETS && defined HAVE_INET_SOCKETS | 735 | #if defined HAVE_SOCKETS && defined HAVE_INET_SOCKETS |
| 736 | 736 | ||
| 737 | enum { AUTH_KEY_LENGTH = 64 }; | 737 | # ifndef NO_SOCKETS_IN_FILE_SYSTEM |
| 738 | static void act_on_signals (HSOCKET); | ||
| 739 | # else | ||
| 740 | static void act_on_signals (HSOCKET s) {} | ||
| 741 | # endif | ||
| 738 | 742 | ||
| 739 | /* Socket used to communicate with the Emacs server process. */ | 743 | enum { AUTH_KEY_LENGTH = 64 }; |
| 740 | static HSOCKET emacs_socket = 0; | ||
| 741 | 744 | ||
| 742 | static void | 745 | static void |
| 743 | sock_err_message (const char *function_name) | 746 | sock_err_message (const char *function_name) |
| @@ -790,16 +793,22 @@ send_to_emacs (HSOCKET s, const char *data) | |||
| 790 | if (sblen == SEND_BUFFER_SIZE | 793 | if (sblen == SEND_BUFFER_SIZE |
| 791 | || (0 < sblen && send_buffer[sblen - 1] == '\n')) | 794 | || (0 < sblen && send_buffer[sblen - 1] == '\n')) |
| 792 | { | 795 | { |
| 793 | int sent = send (s, send_buffer, sblen, 0); | 796 | int sent; |
| 794 | if (sent < 0) | 797 | while ((sent = send (s, send_buffer, sblen, 0)) < 0) |
| 795 | { | 798 | { |
| 796 | message (true, "%s: failed to send %d bytes to socket: %s\n", | 799 | if (errno != EINTR) |
| 797 | progname, sblen, strerror (errno)); | 800 | { |
| 798 | fail (); | 801 | message (true, "%s: failed to send %d bytes to socket: %s\n", |
| 802 | progname, sblen, strerror (errno)); | ||
| 803 | fail (); | ||
| 804 | } | ||
| 805 | /* Act on signals not requiring communication to Emacs, | ||
| 806 | but defer action on the others to avoid confusing the | ||
| 807 | communication currently in progress. */ | ||
| 808 | act_on_signals (INVALID_SOCKET); | ||
| 799 | } | 809 | } |
| 800 | if (sent != sblen) | ||
| 801 | memmove (send_buffer, &send_buffer[sent], sblen - sent); | ||
| 802 | sblen -= sent; | 810 | sblen -= sent; |
| 811 | memmove (send_buffer, &send_buffer[sent], sblen); | ||
| 803 | } | 812 | } |
| 804 | 813 | ||
| 805 | dlen -= part; | 814 | dlen -= part; |
| @@ -1091,86 +1100,181 @@ socket_status (const char *name) | |||
| 1091 | } | 1100 | } |
| 1092 | 1101 | ||
| 1093 | 1102 | ||
| 1094 | /* A signal handler that passes the signal to the Emacs process. | 1103 | /* Signal handlers merely set a flag, to avoid race conditions on |
| 1095 | Useful for SIGWINCH. */ | 1104 | POSIXish systems. Non-POSIX platforms lacking sigaction make do |
| 1096 | 1105 | with traditional calls to 'signal'; races are rare so this usually | |
| 1106 | works. Although this approach may treat multiple deliveries of SIG | ||
| 1107 | as a single delivery and may act on signals in a different order | ||
| 1108 | than received, that is OK for emacsclient. Also, this approach may | ||
| 1109 | omit output if a printf call is interrupted by a signal, but printf | ||
| 1110 | output is not that important (emacsclient does not check for printf | ||
| 1111 | errors, after all) so this is also OK for emacsclient. */ | ||
| 1112 | |||
| 1113 | /* Reinstall for SIG the signal handler HANDLER if needed. It is | ||
| 1114 | needed on a non-POSIX or traditional platform where an interrupt | ||
| 1115 | resets the signal handler to SIG_DFL. */ | ||
| 1097 | static void | 1116 | static void |
| 1098 | pass_signal_to_emacs (int signalnum) | 1117 | reinstall_handler_if_needed (int sig, void (*handler) (int)) |
| 1099 | { | 1118 | { |
| 1100 | int old_errno = errno; | 1119 | # ifndef SA_RESETHAND |
| 1120 | /* This is a platform without POSIX's sigaction. */ | ||
| 1121 | signal (sig, handler); | ||
| 1122 | # endif | ||
| 1123 | } | ||
| 1101 | 1124 | ||
| 1102 | if (emacs_pid) | 1125 | /* Flags for each signal, and handlers that set the flags. */ |
| 1103 | kill (emacs_pid, signalnum); | ||
| 1104 | 1126 | ||
| 1105 | signal (signalnum, pass_signal_to_emacs); | 1127 | static sig_atomic_t volatile |
| 1106 | errno = old_errno; | 1128 | got_sigcont, got_sigtstp, got_sigttou, got_sigwinch; |
| 1129 | |||
| 1130 | static void | ||
| 1131 | handle_sigcont (int sig) | ||
| 1132 | { | ||
| 1133 | got_sigcont = 1; | ||
| 1134 | reinstall_handler_if_needed (sig, handle_sigcont); | ||
| 1135 | } | ||
| 1136 | static void | ||
| 1137 | handle_sigtstp (int sig) | ||
| 1138 | { | ||
| 1139 | got_sigtstp = 1; | ||
| 1140 | reinstall_handler_if_needed (sig, handle_sigtstp); | ||
| 1141 | } | ||
| 1142 | static void | ||
| 1143 | handle_sigttou (int sig) | ||
| 1144 | { | ||
| 1145 | got_sigttou = 1; | ||
| 1146 | reinstall_handler_if_needed (sig, handle_sigttou); | ||
| 1147 | } | ||
| 1148 | static void | ||
| 1149 | handle_sigwinch (int sig) | ||
| 1150 | { | ||
| 1151 | got_sigwinch = 1; | ||
| 1152 | reinstall_handler_if_needed (sig, handle_sigwinch); | ||
| 1107 | } | 1153 | } |
| 1108 | 1154 | ||
| 1109 | /* Signal handler for SIGCONT; notify the Emacs process that it can | 1155 | /* Install for signal SIG the handler HANDLER. However, if FLAG is |
| 1110 | now resume our tty frame. */ | 1156 | non-null and if the signal is currently being ignored, do not |
| 1157 | install the handler and keep *FLAG zero. */ | ||
| 1111 | 1158 | ||
| 1112 | static void | 1159 | static void |
| 1113 | handle_sigcont (int signalnum) | 1160 | install_handler (int sig, void (*handler) (int), sig_atomic_t volatile *flag) |
| 1114 | { | 1161 | { |
| 1115 | int old_errno = errno; | 1162 | # ifdef SA_RESETHAND |
| 1116 | pid_t pgrp = getpgrp (); | 1163 | if (flag) |
| 1117 | pid_t tcpgrp = tcgetpgrp (STDOUT_FILENO); | ||
| 1118 | |||
| 1119 | if (tcpgrp == pgrp) | ||
| 1120 | { | 1164 | { |
| 1121 | /* We are in the foreground. */ | 1165 | struct sigaction oact; |
| 1122 | send_to_emacs (emacs_socket, "-resume \n"); | 1166 | if (sigaction (sig, NULL, &oact) == 0 && oact.sa_handler == SIG_IGN) |
| 1167 | return; | ||
| 1123 | } | 1168 | } |
| 1124 | else if (0 <= tcpgrp && tty) | 1169 | struct sigaction act = { .sa_handler = handler }; |
| 1170 | sigemptyset (&act.sa_mask); | ||
| 1171 | sigaction (sig, &act, NULL); | ||
| 1172 | # else | ||
| 1173 | void (*ohandler) (int) = signal (sig, handler); | ||
| 1174 | if (flag) | ||
| 1125 | { | 1175 | { |
| 1126 | /* We are in the background; cancel the continue. */ | 1176 | if (ohandler == SIG_IGN) |
| 1127 | kill (-pgrp, SIGTTIN); | 1177 | { |
| 1178 | signal (sig, SIG_IGN); | ||
| 1179 | /* While HANDLER was mistakenly installed a signal may have | ||
| 1180 | arrived and set *FLAG, so clear *FLAG now. */ | ||
| 1181 | *flag = 0; | ||
| 1182 | } | ||
| 1128 | } | 1183 | } |
| 1129 | 1184 | # endif | |
| 1130 | signal (signalnum, handle_sigcont); | ||
| 1131 | errno = old_errno; | ||
| 1132 | } | 1185 | } |
| 1133 | 1186 | ||
| 1134 | /* Signal handler for SIGTSTP; notify the Emacs process that we are | 1187 | /* Initial installation of signal handlers. */ |
| 1135 | going to sleep. Normally the suspend is initiated by Emacs via | ||
| 1136 | server-handle-suspend-tty, but if the server gets out of sync with | ||
| 1137 | reality, we may get a SIGTSTP on C-z. Handling this signal and | ||
| 1138 | notifying Emacs about it should get things under control again. */ | ||
| 1139 | 1188 | ||
| 1140 | static void | 1189 | static void |
| 1141 | handle_sigtstp (int signalnum) | 1190 | init_signals (void) |
| 1142 | { | 1191 | { |
| 1143 | int old_errno = errno; | 1192 | install_handler (SIGCONT, handle_sigcont, &got_sigcont); |
| 1144 | sigset_t set; | 1193 | install_handler (SIGTSTP, handle_sigtstp, &got_sigtstp); |
| 1145 | 1194 | install_handler (SIGTTOU, handle_sigttou, &got_sigttou); | |
| 1146 | if (emacs_socket) | 1195 | install_handler (SIGWINCH, handle_sigwinch, &got_sigwinch); |
| 1147 | send_to_emacs (emacs_socket, "-suspend \n"); | 1196 | /* Don't mess with SIGINT and SIGQUIT, as Emacs has no way to |
| 1148 | 1197 | determine which terminal the signal came from. C-g is a normal | |
| 1149 | /* Unblock this signal and call the default handler by temporarily | 1198 | input event on secondary terminals. */ |
| 1150 | changing the handler and resignaling. */ | ||
| 1151 | sigprocmask (SIG_BLOCK, NULL, &set); | ||
| 1152 | sigdelset (&set, signalnum); | ||
| 1153 | signal (signalnum, SIG_DFL); | ||
| 1154 | raise (signalnum); | ||
| 1155 | sigprocmask (SIG_SETMASK, &set, NULL); /* Let's the above signal through. */ | ||
| 1156 | signal (signalnum, handle_sigtstp); | ||
| 1157 | |||
| 1158 | errno = old_errno; | ||
| 1159 | } | 1199 | } |
| 1160 | 1200 | ||
| 1201 | /* Act on delivered tty-related signal SIG that normally has handler | ||
| 1202 | HANDLER. EMACS_SOCKET connects to Emacs. */ | ||
| 1161 | 1203 | ||
| 1162 | /* Set up signal handlers before opening a frame on the current tty. */ | 1204 | static void |
| 1205 | act_on_tty_signal (int sig, void (*handler) (int), HSOCKET emacs_socket) | ||
| 1206 | { | ||
| 1207 | /* Notify Emacs that we are going to sleep. Normally the suspend is | ||
| 1208 | initiated by Emacs via server-handle-suspend-tty, but if the | ||
| 1209 | server gets out of sync with reality, we may get a SIGTSTP on | ||
| 1210 | C-z. Handling this signal and notifying Emacs about it should | ||
| 1211 | get things under control again. */ | ||
| 1212 | send_to_emacs (emacs_socket, "-suspend \n"); | ||
| 1213 | |||
| 1214 | /* Execute the default action by temporarily changing handling to | ||
| 1215 | the default and resignaling. */ | ||
| 1216 | install_handler (sig, SIG_DFL, NULL); | ||
| 1217 | raise (sig); | ||
| 1218 | install_handler (sig, handler, NULL); | ||
| 1219 | } | ||
| 1220 | |||
| 1221 | /* Act on delivered signals if possible. If EMACS_SOCKET is valid, | ||
| 1222 | use it to communicate to Emacs. */ | ||
| 1163 | 1223 | ||
| 1164 | static void | 1224 | static void |
| 1165 | init_signals (void) | 1225 | act_on_signals (HSOCKET emacs_socket) |
| 1166 | { | 1226 | { |
| 1167 | /* Don't pass SIGINT and SIGQUIT to Emacs, because it has no way of | 1227 | while (true) |
| 1168 | deciding which terminal the signal came from. C-g is now a | 1228 | { |
| 1169 | normal input event on secondary terminals. */ | 1229 | bool took_action = false; |
| 1170 | signal (SIGWINCH, pass_signal_to_emacs); | 1230 | |
| 1171 | signal (SIGCONT, handle_sigcont); | 1231 | if (emacs_socket != INVALID_SOCKET) |
| 1172 | signal (SIGTSTP, handle_sigtstp); | 1232 | { |
| 1173 | signal (SIGTTOU, handle_sigtstp); | 1233 | if (got_sigcont) |
| 1234 | { | ||
| 1235 | got_sigcont = 0; | ||
| 1236 | took_action = true; | ||
| 1237 | pid_t tcpgrp = tcgetpgrp (STDOUT_FILENO); | ||
| 1238 | if (0 <= tcpgrp) | ||
| 1239 | { | ||
| 1240 | pid_t pgrp = getpgrp (); | ||
| 1241 | if (tcpgrp == pgrp) | ||
| 1242 | { | ||
| 1243 | /* We are in the foreground. */ | ||
| 1244 | send_to_emacs (emacs_socket, "-resume \n"); | ||
| 1245 | } | ||
| 1246 | else if (tty) | ||
| 1247 | { | ||
| 1248 | /* We are in the background; cancel the continue. */ | ||
| 1249 | kill (-pgrp, SIGTTIN); | ||
| 1250 | } | ||
| 1251 | } | ||
| 1252 | } | ||
| 1253 | |||
| 1254 | if (got_sigtstp) | ||
| 1255 | { | ||
| 1256 | got_sigtstp = 0; | ||
| 1257 | took_action = true; | ||
| 1258 | act_on_tty_signal (SIGTSTP, handle_sigtstp, emacs_socket); | ||
| 1259 | } | ||
| 1260 | if (got_sigttou) | ||
| 1261 | { | ||
| 1262 | got_sigttou = 0; | ||
| 1263 | took_action = true; | ||
| 1264 | act_on_tty_signal (SIGTTOU, handle_sigttou, emacs_socket); | ||
| 1265 | } | ||
| 1266 | } | ||
| 1267 | |||
| 1268 | if (emacs_pid && got_sigwinch) | ||
| 1269 | { | ||
| 1270 | got_sigwinch = 0; | ||
| 1271 | took_action = true; | ||
| 1272 | kill (emacs_pid, SIGWINCH); | ||
| 1273 | } | ||
| 1274 | |||
| 1275 | if (!took_action) | ||
| 1276 | break; | ||
| 1277 | } | ||
| 1174 | } | 1278 | } |
| 1175 | 1279 | ||
| 1176 | /* Create a local socket and connect it to Emacs. */ | 1280 | /* Create a local socket and connect it to Emacs. */ |
| @@ -1464,7 +1568,7 @@ w32_give_focus (void) | |||
| 1464 | 1568 | ||
| 1465 | /* Start the emacs daemon and try to connect to it. */ | 1569 | /* Start the emacs daemon and try to connect to it. */ |
| 1466 | 1570 | ||
| 1467 | static void | 1571 | static HSOCKET |
| 1468 | start_daemon_and_retry_set_socket (void) | 1572 | start_daemon_and_retry_set_socket (void) |
| 1469 | { | 1573 | { |
| 1470 | # ifndef WINDOWSNT | 1574 | # ifndef WINDOWSNT |
| @@ -1581,13 +1685,23 @@ start_daemon_and_retry_set_socket (void) | |||
| 1581 | "Emacs daemon should have started, trying to connect again\n"); | 1685 | "Emacs daemon should have started, trying to connect again\n"); |
| 1582 | # endif /* WINDOWSNT */ | 1686 | # endif /* WINDOWSNT */ |
| 1583 | 1687 | ||
| 1584 | emacs_socket = set_socket (true); | 1688 | HSOCKET emacs_socket = set_socket (true); |
| 1585 | if (emacs_socket == INVALID_SOCKET) | 1689 | if (emacs_socket == INVALID_SOCKET) |
| 1586 | { | 1690 | { |
| 1587 | message (true, | 1691 | message (true, |
| 1588 | "Error: Cannot connect even after starting the Emacs daemon\n"); | 1692 | "Error: Cannot connect even after starting the Emacs daemon\n"); |
| 1589 | exit (EXIT_FAILURE); | 1693 | exit (EXIT_FAILURE); |
| 1590 | } | 1694 | } |
| 1695 | return emacs_socket; | ||
| 1696 | } | ||
| 1697 | |||
| 1698 | /* Flush standard output and its underlying file descriptor. */ | ||
| 1699 | static void | ||
| 1700 | flush_stdout (HSOCKET emacs_socket) | ||
| 1701 | { | ||
| 1702 | fflush (stdout); | ||
| 1703 | while (fdatasync (STDOUT_FILENO) != 0 && errno == EINTR) | ||
| 1704 | act_on_signals (emacs_socket); | ||
| 1591 | } | 1705 | } |
| 1592 | #endif /* HAVE_SOCKETS && HAVE_INET_SOCKETS */ | 1706 | #endif /* HAVE_SOCKETS && HAVE_INET_SOCKETS */ |
| 1593 | 1707 | ||
| @@ -1641,13 +1755,14 @@ main (int argc, char **argv) | |||
| 1641 | in case of failure to connect. */ | 1755 | in case of failure to connect. */ |
| 1642 | bool start_daemon_if_needed = alternate_editor && !alternate_editor[0]; | 1756 | bool start_daemon_if_needed = alternate_editor && !alternate_editor[0]; |
| 1643 | 1757 | ||
| 1644 | emacs_socket = set_socket (alternate_editor || start_daemon_if_needed); | 1758 | HSOCKET emacs_socket = set_socket (alternate_editor |
| 1759 | || start_daemon_if_needed); | ||
| 1645 | if (emacs_socket == INVALID_SOCKET) | 1760 | if (emacs_socket == INVALID_SOCKET) |
| 1646 | { | 1761 | { |
| 1647 | if (! start_daemon_if_needed) | 1762 | if (! start_daemon_if_needed) |
| 1648 | fail (); | 1763 | fail (); |
| 1649 | 1764 | ||
| 1650 | start_daemon_and_retry_set_socket (); | 1765 | emacs_socket = start_daemon_and_retry_set_socket (); |
| 1651 | } | 1766 | } |
| 1652 | 1767 | ||
| 1653 | char *cwd = get_current_dir_name (); | 1768 | char *cwd = get_current_dir_name (); |
| @@ -1719,6 +1834,8 @@ main (int argc, char **argv) | |||
| 1719 | if (find_tty (&tty_type, &tty_name, !tty)) | 1834 | if (find_tty (&tty_type, &tty_name, !tty)) |
| 1720 | { | 1835 | { |
| 1721 | # ifndef NO_SOCKETS_IN_FILE_SYSTEM | 1836 | # ifndef NO_SOCKETS_IN_FILE_SYSTEM |
| 1837 | /* Install signal handlers before opening a frame on the | ||
| 1838 | current tty. */ | ||
| 1722 | init_signals (); | 1839 | init_signals (); |
| 1723 | # endif | 1840 | # endif |
| 1724 | send_to_emacs (emacs_socket, "-tty "); | 1841 | send_to_emacs (emacs_socket, "-tty "); |
| @@ -1809,20 +1926,16 @@ main (int argc, char **argv) | |||
| 1809 | printf ("Waiting for Emacs..."); | 1926 | printf ("Waiting for Emacs..."); |
| 1810 | skiplf = false; | 1927 | skiplf = false; |
| 1811 | } | 1928 | } |
| 1812 | fflush (stdout); | 1929 | flush_stdout (emacs_socket); |
| 1813 | while (fdatasync (STDOUT_FILENO) != 0 && errno == EINTR) | ||
| 1814 | continue; | ||
| 1815 | 1930 | ||
| 1816 | /* Now, wait for an answer and print any messages. */ | 1931 | /* Now, wait for an answer and print any messages. */ |
| 1817 | while (exit_status == EXIT_SUCCESS) | 1932 | while (exit_status == EXIT_SUCCESS) |
| 1818 | { | 1933 | { |
| 1819 | do | 1934 | do |
| 1820 | { | 1935 | { |
| 1821 | errno = 0; | 1936 | act_on_signals (emacs_socket); |
| 1822 | rl = recv (emacs_socket, string, BUFSIZ, 0); | 1937 | rl = recv (emacs_socket, string, BUFSIZ, 0); |
| 1823 | } | 1938 | } |
| 1824 | /* If we receive a signal (e.g. SIGWINCH, which we pass | ||
| 1825 | through to Emacs), on some OSes we get EINTR and must retry. */ | ||
| 1826 | while (rl < 0 && errno == EINTR); | 1939 | while (rl < 0 && errno == EINTR); |
| 1827 | 1940 | ||
| 1828 | if (rl <= 0) | 1941 | if (rl <= 0) |
| @@ -1916,9 +2029,7 @@ main (int argc, char **argv) | |||
| 1916 | 2029 | ||
| 1917 | if (!skiplf) | 2030 | if (!skiplf) |
| 1918 | printf ("\n"); | 2031 | printf ("\n"); |
| 1919 | fflush (stdout); | 2032 | flush_stdout (emacs_socket); |
| 1920 | while (fdatasync (STDOUT_FILENO) != 0 && errno == EINTR) | ||
| 1921 | continue; | ||
| 1922 | 2033 | ||
| 1923 | if (rl < 0) | 2034 | if (rl < 0) |
| 1924 | exit_status = EXIT_FAILURE; | 2035 | exit_status = EXIT_FAILURE; |