Commit d5e3f5cb authored by Anton Ivanov's avatar Anton Ivanov Committed by Richard Weinberger

um: Prevent IRQ handler reentrancy

The existing IRQ handler design in UML does not prevent reentrancy

This is mitigated by fd-enable/fd-disable semantics for the IO
portion of the UML subsystem. The timer, however, can and is
re-entered resulting in very deep stack usage and occasional
stack exhaustion.

This patch prevents this by checking if there is a timer
interrupt in-flight before processing any pending timer interrupts.
Signed-off-by: default avatarAnton Ivanov <aivanov@brocade.com>
Signed-off-by: default avatarRichard Weinberger <richard@nod.at>
parent 0754fb29
...@@ -62,6 +62,7 @@ static void sig_handler_common(int sig, struct siginfo *si, mcontext_t *mc) ...@@ -62,6 +62,7 @@ static void sig_handler_common(int sig, struct siginfo *si, mcontext_t *mc)
static int signals_enabled; static int signals_enabled;
static unsigned int signals_pending; static unsigned int signals_pending;
static unsigned int signals_active = 0;
void sig_handler(int sig, struct siginfo *si, mcontext_t *mc) void sig_handler(int sig, struct siginfo *si, mcontext_t *mc)
{ {
...@@ -101,7 +102,12 @@ void timer_alarm_handler(int sig, struct siginfo *unused_si, mcontext_t *mc) ...@@ -101,7 +102,12 @@ void timer_alarm_handler(int sig, struct siginfo *unused_si, mcontext_t *mc)
block_signals(); block_signals();
signals_active |= SIGALRM_MASK;
timer_real_alarm_handler(mc); timer_real_alarm_handler(mc);
signals_active &= ~SIGALRM_MASK;
set_signals(enabled); set_signals(enabled);
} }
...@@ -286,8 +292,16 @@ void unblock_signals(void) ...@@ -286,8 +292,16 @@ void unblock_signals(void)
if (save_pending & SIGIO_MASK) if (save_pending & SIGIO_MASK)
sig_handler_common(SIGIO, NULL, NULL); sig_handler_common(SIGIO, NULL, NULL);
if (save_pending & SIGALRM_MASK) /* Do not reenter the handler */
if ((save_pending & SIGALRM_MASK) && (!(signals_active & SIGALRM_MASK)))
timer_real_alarm_handler(NULL); timer_real_alarm_handler(NULL);
/* Rerun the loop only if there is still pending SIGIO and not in TIMER handler */
if (!(signals_pending & SIGIO_MASK) && (signals_active & SIGALRM_MASK))
return;
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment