Merge "Respect HW configs when loading VM from snapshots."
diff --git a/distrib/sdl-1.2.12/src/video/x11/SDL_x11dyn.c b/distrib/sdl-1.2.12/src/video/x11/SDL_x11dyn.c
index 883c235..7b99d73 100644
--- a/distrib/sdl-1.2.12/src/video/x11/SDL_x11dyn.c
+++ b/distrib/sdl-1.2.12/src/video/x11/SDL_x11dyn.c
@@ -170,6 +170,7 @@
 
 		if (SDL_X11_HAVE_BASEXLIB) {  /* all required symbols loaded. */
 			SDL_ClearError();
+			XInitThreads();
 		} else {
 			SDL_X11_UnloadSymbols();  /* in case something got loaded... */
 			rc = 0;
diff --git a/distrib/sdl-1.2.12/src/video/x11/SDL_x11sym.h b/distrib/sdl-1.2.12/src/video/x11/SDL_x11sym.h
index c4df1f6..b8d90e4 100644
--- a/distrib/sdl-1.2.12/src/video/x11/SDL_x11sym.h
+++ b/distrib/sdl-1.2.12/src/video/x11/SDL_x11sym.h
@@ -70,6 +70,7 @@
 SDL_X11_SYM(int,XGrabKeyboard,(Display* a,Window b,Bool c,int d,int e,Time f),(a,b,c,d,e,f),return)
 SDL_X11_SYM(int,XGrabPointer,(Display* a,Window b,Bool c,unsigned int d,int e,int f,Window g,Cursor h,Time i),(a,b,c,d,e,f,g,h,i),return)
 SDL_X11_SYM(Status,XIconifyWindow,(Display* a,Window b,int c),(a,b,c),return)
+SDL_X11_SYM(Status,XInitThreads,(void),(),return)
 SDL_X11_SYM(int,XInstallColormap,(Display* a,Colormap b),(a,b),return)
 SDL_X11_SYM(KeyCode,XKeysymToKeycode,(Display* a,KeySym b),(a,b),return)
 SDL_X11_SYM(Atom,XInternAtom,(Display* a,_Xconst char* b,Bool c),(a,b,c),return)
diff --git a/target-i386/kvm-gs-restore.c b/target-i386/kvm-gs-restore.c
index a0ff565..2ca6ab6 100644
--- a/target-i386/kvm-gs-restore.c
+++ b/target-i386/kvm-gs-restore.c
@@ -32,61 +32,104 @@
     restoregs(initial_gs);
 }
 
-static struct sigaction old_alarm_act, old_gio_act, old_pipe_act,old_usr1_act, old_chld_act;
-static void temp_sig_handler(int host_signum)
+struct sigact_status
+{
+    unsigned int sigaction:1;
+    __sighandler_t old_handler;
+    void (*old_sigaction) (int, siginfo_t *, void *);
+};
+static struct sigact_status o_sigact[SIGUNUSED];
+
+static void temp_sig_handler(int signum)
 {
     /* !!! must restore gs firstly */
     check_and_restore_gs();
-    switch (host_signum)
+
+    if (signum < SIGHUP || signum >= SIGUNUSED)
     {
-    case SIGALRM:
-        old_alarm_act.sa_handler(host_signum);
-        break;
+        fprintf(stderr, "Invalid signal %x in temp_sig_handler\n", signum);
+        abort();
+    }
 
-    case SIGIO:
-        old_gio_act.sa_handler(host_signum);
-        break;
+    if ( !o_sigact[signum].sigaction && o_sigact[signum].old_handler)
+        o_sigact[signum].old_handler(signum);
+    else
+    {
+        fprintf(stderr, "Invalid signal in temp_sig_handler: "
+             "signal %x sa_info %s!!\n",
+             signum, o_sigact[signum].sigaction ? "set":"not set" );
+         abort();
+    }
+}
 
-    case SIGUSR1:
-        old_usr1_act.sa_handler(host_signum);
-        break;
+static void temp_sig_sigaction(int signum, siginfo_t *info, void *ucontext)
+{
+    /* !!! must restore gs firstly */
+    check_and_restore_gs();
 
-    case SIGPIPE:
-        old_pipe_act.sa_handler(host_signum);
-        break;
+    if (signum < SIGHUP || signum >= SIGUNUSED)
+    {
+        fprintf(stderr, "Invalid signal %x in temp_sig_sigaction\n", signum);
+        abort();
+    }
 
-    case SIGCHLD:
-        old_chld_act.sa_handler(host_signum);
-        break;
-
-    default:
-        fprintf(stderr, "Not take signal %x!!\n", host_signum);
-        break;
+    if ( o_sigact[signum].sigaction && o_sigact[signum].old_sigaction )
+        o_sigact[signum].old_sigaction(signum, info, ucontext);
+    else
+    {
+        fprintf(stderr, "Invalid signal in temp_sig_sigaction: "
+             "signal %x sa_info %s!!\n",
+             signum, o_sigact[signum].sigaction ? "set":"not set" );
+         abort();
     }
 }
 
 static int sig_taken = 0;
+
 static int take_signal_handler(void)
 {
-    struct sigaction act;
-    int ret;
+    int i;
 
     if (gs_need_restore == KVM_GS_RESTORE_NO)
         return 0;
     if (sig_taken)
         return 0;
 
+    memset(o_sigact, 0, sizeof(o_sigact));
+
+    /* SIGHUP is 1 in POSIX */
+    for (i = SIGHUP; i < SIGUNUSED; i++)
+    {
+        int sigret;
+        struct sigaction act, old_act;
+
+        sigret = sigaction(i, NULL, &old_act);
+        if (sigret)
+            continue;
+        /* We don't need take the handler for default or ignore signals */
+        if ( !(old_act.sa_flags & SA_SIGINFO) &&
+               ((old_act.sa_handler == SIG_IGN ) ||
+                (old_act.sa_handler == SIG_DFL)))
+            continue;
+
+        memcpy(&act, &old_act, sizeof(struct sigaction));
+
+        if (old_act.sa_flags & SA_SIGINFO)
+        {
+            o_sigact[i].old_sigaction = old_act.sa_sigaction;
+            o_sigact[i].sigaction = 1;
+            act.sa_sigaction = temp_sig_sigaction;
+        }
+        else
+        {
+            o_sigact[i].old_handler = old_act.sa_handler;
+            act.sa_handler = temp_sig_handler;
+        }
+
+        sigaction(i, &act, NULL);
+        continue;
+    }
     sig_taken = 1;
-    sigfillset(&act.sa_mask);
-    act.sa_flags = 0;
-    act.sa_handler = temp_sig_handler;
-    /* Did we missed any other signal ? */
-    sigaction(SIGALRM, &act, &old_alarm_act);
-    sigaction(SIGIO, &act, &old_gio_act);
-    sigaction(SIGUSR1, &act, &old_usr1_act);
-    sigaction(SIGPIPE, &act, &old_pipe_act);
-    act.sa_flags = SA_NOCLDSTOP;
-    sigaction(SIGCHLD, &act, &old_chld_act);
     return 1;
 }