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
*/