mingw: make fgetc raise SIGINT if apropriate

Set a control-handler to prevent the process from terminating, and simulate SIGINT so it can be handled by a signal-handler as usual. Signed-off-by: Erik Faye-Lund <kusmabite@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Erik Faye-Lund committed Dec 4, 2012 at 09:10 UTC 176478a8bd028a3877d2be49a1e7a49386c095ce
2 files changed +72 -10
compat/mingw.c
+66 -10
@@ -319,6 +319,31 @@ ssize_t mingw_write(int fd, const void *buf, size_t count)
319 return write(fd, buf, min(count, 31 * 1024 * 1024));
320 }
321
322 +static BOOL WINAPI ctrl_ignore(DWORD type)
323 +{
324 + return TRUE;
325 +}
326 +
327 +#undef fgetc
328 +int mingw_fgetc(FILE *stream)
329 +{
330 + int ch;
331 + if (!isatty(_fileno(stream)))
332 + return fgetc(stream);
333 +
334 + SetConsoleCtrlHandler(ctrl_ignore, TRUE);
335 + while (1) {
336 + ch = fgetc(stream);
337 + if (ch != EOF || GetLastError() != ERROR_OPERATION_ABORTED)
338 + break;
339 +
340 + /* Ctrl+C was pressed, simulate SIGINT and retry */
341 + mingw_raise(SIGINT);
342 + }
343 + SetConsoleCtrlHandler(ctrl_ignore, FALSE);
344 + return ch;
345 +}
346 +
347 #undef fopen
348 FILE *mingw_fopen (const char *filename, const char *otype)
349 {
@@ -1546,7 +1571,7 @@ static HANDLE timer_event;
1571 static HANDLE timer_thread;
1572 static int timer_interval;
1573 static int one_shot;
1549 -static sig_handler_t timer_fn = SIG_DFL;
1574 +static sig_handler_t timer_fn = SIG_DFL, sigint_fn = SIG_DFL;
1575
1576 /* The timer works like this:
1577 * The thread, ticktack(), is a trivial routine that most of the time
@@ -1560,13 +1585,7 @@ static sig_handler_t timer_fn = SIG_DFL;
1585 static unsigned __stdcall ticktack(void *dummy)
1586 {
1587 while (WaitForSingleObject(timer_event, timer_interval) == WAIT_TIMEOUT) {
1563 - if (timer_fn == SIG_DFL) {
1564 - if (isatty(STDERR_FILENO))
1565 - fputs("Alarm clock\n", stderr);
1566 - exit(128 + SIGALRM);
1567 - }
1568 - if (timer_fn != SIG_IGN)
1569 - timer_fn(SIGALRM);
1588 + mingw_raise(SIGALRM);
1589 if (one_shot)
1590 break;
1591 }
@@ -1657,12 +1676,49 @@ int sigaction(int sig, struct sigaction *in, struct sigaction *out)
1676 sig_handler_t mingw_signal(int sig, sig_handler_t handler)
1677 {
1678 sig_handler_t old = timer_fn;
1660 - if (sig != SIGALRM)
1679 +
1680 + switch (sig) {
1681 + case SIGALRM:
1682 + timer_fn = handler;
1683 + break;
1684 +
1685 + case SIGINT:
1686 + sigint_fn = handler;
1687 + break;
1688 +
1689 + default:
1690 return signal(sig, handler);
1662 - timer_fn = handler;
1691 + }
1692 +
1693 return old;
1694 }
1695
1696 +#undef raise
1697 +int mingw_raise(int sig)
1698 +{
1699 + switch (sig) {
1700 + case SIGALRM:
1701 + if (timer_fn == SIG_DFL) {
1702 + if (isatty(STDERR_FILENO))
1703 + fputs("Alarm clock\n", stderr);
1704 + exit(128 + SIGALRM);
1705 + } else if (timer_fn != SIG_IGN)
1706 + timer_fn(SIGALRM);
1707 + return 0;
1708 +
1709 + case SIGINT:
1710 + if (sigint_fn == SIG_DFL)
1711 + exit(128 + SIGINT);
1712 + else if (sigint_fn != SIG_IGN)
1713 + sigint_fn(SIGINT);
1714 + return 0;
1715 +
1716 + default:
1717 + return raise(sig);
1718 + }
1719 +}
1720 +
1721 +
1722 static const char *make_backslash_path(const char *path)
1723 {
1724 static char buf[PATH_MAX + 1];
compat/mingw.h
+6
@@ -179,6 +179,9 @@ int mingw_open (const char *filename, int oflags, ...);
179 ssize_t mingw_write(int fd, const void *buf, size_t count);
180 #define write mingw_write
181
182 +int mingw_fgetc(FILE *stream);
183 +#define fgetc mingw_fgetc
184 +
185 FILE *mingw_fopen (const char *filename, const char *otype);
186 #define fopen mingw_fopen
187
@@ -290,6 +293,9 @@ static inline unsigned int git_ntohl(unsigned int x)
293 sig_handler_t mingw_signal(int sig, sig_handler_t handler);
294 #define signal mingw_signal
295
296 +int mingw_raise(int sig);
297 +#define raise mingw_raise
298 +
299 /*
300 * ANSI emulation wrappers
301 */