Hi, There is a chance that when using "unix" or "dynticks" clock, the signal arrives when no cpu is executing. The probability is high when using dynticks and a timer is scheduled to expire very soon so that a signal is delivered very soon after a previous signal. When that happens cpu_single_env is zero and the signal handler does nothing. This is not much problem with "unix" clocks or when not using -nographic or when the guest OS uses interrupts, because a another cpu_loop_exit will happen in not too long. If none of these conditions is true the cpu loop starts spinning without a chance to exit and process events. I used the following patch to prevent this but there's probably a better way:
diff --git a/cpu-all.h b/cpu-all.h index f4db592..c095e9c 100644 --- a/cpu-all.h +++ b/cpu-all.h @@ -706,6 +706,7 @@ void cpu_abort(CPUState *env, const char *fmt, ...) __attribute__ ((__noreturn__)); extern CPUState *first_cpu; extern CPUState *cpu_single_env; +extern int env_pending_request; extern int code_copy_enabled; #define CPU_INTERRUPT_EXIT 0x01 /* wants exit from main loop */ diff --git a/cpu-exec.c b/cpu-exec.c index 1c7356a..af75731 100644 --- a/cpu-exec.c +++ b/cpu-exec.c @@ -258,6 +258,11 @@ int cpu_exec(CPUState *env1) cpu_single_env = env1; + if (env_pending_request) { + cpu_interrupt(env1, env_pending_request); + env_pending_request = 0; + } + /* first we save global registers */ #define SAVE_HOST_REGS 1 #include "hostregs_helper.h" diff --git a/exec.c b/exec.c index 6384df2..a649d8f 100644 --- a/exec.c +++ b/exec.c @@ -96,6 +96,7 @@ CPUState *first_cpu; /* current CPU in the current thread. It is only valid inside cpu_exec() */ CPUState *cpu_single_env; +int env_pending_request; typedef struct PageDesc { /* list of TBs intersecting this ram page */ @@ -1194,6 +1195,12 @@ void cpu_interrupt(CPUState *env, int mask) TranslationBlock *tb; static int interrupt_lock; + /* cause an interrupt in the first cpu that tries to start running */ + if (!env) { + env_pending_request |= mask; + return; + } + env->interrupt_request |= mask; /* if the cpu is currently executing code, we must unlink it and all the potentially executing TB */ diff --git a/vl.c b/vl.c index 864a044..ec2aa84 100644 --- a/vl.c +++ b/vl.c @@ -1184,15 +1184,14 @@ static void host_alarm_handler(int host_signum) SetEvent(data->host_alarm); #endif CPUState *env = cpu_single_env; - if (env) { - /* stop the currently executing cpu because a timer occured */ - cpu_interrupt(env, CPU_INTERRUPT_EXIT); + + /* stop the currently executing cpu because a timer occured */ + cpu_interrupt(env, CPU_INTERRUPT_EXIT); #ifdef USE_KQEMU - if (env->kqemu_enabled) { - kqemu_cpu_interrupt(env); - } -#endif + if (env && env->kqemu_enabled) { + kqemu_cpu_interrupt(env); } +#endif } } Regards