]> git.ipfire.org Git - thirdparty/xz.git/commitdiff
Fix a Windows-specific FIXME in signal handling code.
authorLasse Collin <lasse.collin@tukaani.org>
Wed, 2 Jun 2010 18:32:12 +0000 (21:32 +0300)
committerLasse Collin <lasse.collin@tukaani.org>
Wed, 2 Jun 2010 18:32:12 +0000 (21:32 +0300)
src/xz/main.c
src/xz/private.h
src/xz/signals.c

index e0905893c89dd0eb69b8ef8e3cae753f3144dd24..8196c6e7e7746ee0c70538c121ff4f991ee68f25 100644 (file)
 #include "private.h"
 #include <ctype.h>
 
-
 /// Exit status to use. This can be changed with set_exit_status().
 static enum exit_status_type exit_status = E_SUCCESS;
 
+#if defined(_WIN32) && !defined(__CYGWIN__)
+/// exit_status has to be protected with a critical section due to
+/// how "signal handling" is done on Windows. See signals.c for details.
+static CRITICAL_SECTION exit_status_cs;
+#endif
+
 /// True if --no-warn is specified. When this is true, we don't set
 /// the exit status to E_WARNING when something worth a warning happens.
 static bool no_warn = false;
@@ -27,9 +32,17 @@ set_exit_status(enum exit_status_type new_status)
 {
        assert(new_status == E_WARNING || new_status == E_ERROR);
 
+#if defined(_WIN32) && !defined(__CYGWIN__)
+       EnterCriticalSection(&exit_status_cs);
+#endif
+
        if (exit_status != E_ERROR)
                exit_status = new_status;
 
+#if defined(_WIN32) && !defined(__CYGWIN__)
+       LeaveCriticalSection(&exit_status_cs);
+#endif
+
        return;
 }
 
@@ -129,6 +142,10 @@ read_name(const args_info *args)
 int
 main(int argc, char **argv)
 {
+#if defined(_WIN32) && !defined(__CYGWIN__)
+       InitializeCriticalSection(&exit_status_cs);
+#endif
+
        // Set up the progname variable.
        tuklib_progname_init(argv);
 
@@ -262,11 +279,24 @@ main(int argc, char **argv)
        // of calling tuklib_exit().
        signals_exit();
 
+       // Make a local copy of exit_status to keep the Windows code
+       // thread safe. At this point it is fine if we miss the user
+       // pressing C-c and don't set the exit_status to E_ERROR on
+       // Windows.
+#if defined(_WIN32) && !defined(__CYGWIN__)
+       EnterCriticalSection(&exit_status_cs);
+#endif
+
+       enum exit_status_type es = exit_status;
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+       LeaveCriticalSection(&exit_status_cs);
+#endif
+
        // Suppress the exit status indicating a warning if --no-warn
        // was specified.
-       if (exit_status == E_WARNING && no_warn)
-               exit_status = E_SUCCESS;
+       if (es == E_WARNING && no_warn)
+               es = E_SUCCESS;
 
-       tuklib_exit(exit_status, E_ERROR,
-                       message_verbosity_get() != V_SILENT);
+       tuklib_exit(es, E_ERROR, message_verbosity_get() != V_SILENT);
 }
index b543435750d88da255c2f83ec8a57a9b21fbab7f..15136bfe878b8061fc0c7c73c2a342c4b66e8e20 100644 (file)
 #include "tuklib_progname.h"
 #include "tuklib_exit.h"
 
+#if defined(_WIN32) && !defined(__CYGWIN__)
+#      define WIN32_LEAN_AND_MEAN
+#      include <windows.h>
+#endif
+
 #ifndef STDIN_FILENO
 #      define STDIN_FILENO (fileno(stdin))
 #endif
index 807b022594b98dcf8d597b7d334b9d4ba44691f2..66d653733224c01d80f3c1148e571229751808b0 100644 (file)
@@ -156,11 +156,14 @@ signals_exit(void)
 #else
 
 // While Windows has some very basic signal handling functions as required
-// by C89, they are not really used, or so I understood. Instead, we use
-// SetConsoleCtrlHandler() to catch user pressing C-c.
-
-#include <windows.h>
-
+// by C89, they are not really used, and e.g. SIGINT doesn't work exactly
+// the way it does on POSIX (Windows creates a new thread for the signal
+// handler). Instead, we use SetConsoleCtrlHandler() to catch user
+// pressing C-c, because that seems to be the recommended way to do it.
+//
+// NOTE: This doesn't work under MSYS. Trying with SIGINT doesn't work
+// either even if it appeared to work at first. So test using Windows
+// console window.
 
 static BOOL WINAPI
 signal_handler(DWORD type lzma_attribute((unused)))
@@ -168,9 +171,6 @@ signal_handler(DWORD type lzma_attribute((unused)))
        // Since we don't get a signal number which we could raise() at
        // signals_exit() like on POSIX, just set the exit status to
        // indicate an error, so that we cannot return with zero exit status.
-       //
-       // FIXME: Since this function runs in its own thread,
-       // set_exit_status() should have a mutex.
        set_exit_status(E_ERROR);
        user_abort = true;
        return TRUE;