Skip to content

Commit 24fee46

Browse files
authored
Merge pull request #2359 from RT-Thread/fix_signal
[Kernel] fix signal issue
2 parents 745659c + 5ae62d0 commit 24fee46

File tree

2 files changed

+92
-57
lines changed

2 files changed

+92
-57
lines changed

src/scheduler.c

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ void rt_schedule(void)
234234

235235
if (rt_interrupt_nest == 0)
236236
{
237-
extern void rt_thread_handle_sig(rt_bool_t clean_state);
237+
extern void rt_thread_handle_sig(void);
238238

239239
rt_hw_context_switch((rt_uint32_t)&from_thread->sp,
240240
(rt_uint32_t)&to_thread->sp);
@@ -243,31 +243,23 @@ void rt_schedule(void)
243243
rt_hw_interrupt_enable(level);
244244

245245
#ifdef RT_USING_SIGNALS
246-
/* check signal status */
247-
rt_thread_handle_sig(RT_TRUE);
246+
/* handle signal */
247+
rt_thread_handle_sig();
248248
#endif
249+
return ;
249250
}
250251
else
251252
{
252253
RT_DEBUG_LOG(RT_DEBUG_SCHEDULER, ("switch in interrupt\n"));
253254

254255
rt_hw_context_switch_interrupt((rt_uint32_t)&from_thread->sp,
255256
(rt_uint32_t)&to_thread->sp);
256-
/* enable interrupt */
257-
rt_hw_interrupt_enable(level);
258257
}
259258
}
260-
else
261-
{
262-
/* enable interrupt */
263-
rt_hw_interrupt_enable(level);
264-
}
265-
}
266-
else
267-
{
268-
/* enable interrupt */
269-
rt_hw_interrupt_enable(level);
270259
}
260+
261+
/* enable interrupt */
262+
rt_hw_interrupt_enable(level);
271263
}
272264

273265
/*

src/signal.c

Lines changed: 85 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
* Change Logs:
77
* Date Author Notes
88
* 2017/10/5 Bernard the first version
9+
* 2019/02/15 Jesven fixed the problem of si_list
910
*/
1011

1112
#include <stdint.h>
@@ -37,7 +38,7 @@ struct siginfo_node
3738

3839
static struct rt_mempool *_rt_siginfo_pool;
3940
static void _signal_deliver(rt_thread_t tid);
40-
void rt_thread_handle_sig(rt_bool_t clean_state);
41+
void rt_thread_handle_sig(void);
4142

4243
static void _signal_default_handler(int signo)
4344
{
@@ -47,22 +48,37 @@ static void _signal_default_handler(int signo)
4748

4849
static void _signal_entry(void *parameter)
4950
{
51+
register rt_base_t level;
5052
rt_thread_t tid = rt_thread_self();
5153

5254
dbg_enter;
5355

54-
/* handle signal */
55-
rt_thread_handle_sig(RT_FALSE);
56+
while (1)
57+
{
58+
level = rt_hw_interrupt_disable();
59+
if (tid->stat & RT_THREAD_STAT_SIGNAL)
60+
{
61+
rt_hw_interrupt_enable(level);
62+
63+
/* handle signal */
64+
rt_thread_handle_sig();
65+
}
66+
else
67+
{
68+
/*
69+
* Note: interrupt is disabled and no reentrant issue.
70+
*
71+
* no signal status in tid->stat.
72+
*/
73+
break;
74+
}
75+
}
5676

5777
/* never come back... */
58-
rt_hw_interrupt_disable();
59-
/* return to thread */
6078
tid->sp = tid->sig_ret;
6179
tid->sig_ret = RT_NULL;
6280

6381
LOG_D("switch back to: 0x%08x", tid->sp);
64-
tid->stat &= ~RT_THREAD_STAT_SIGNAL;
65-
6682
rt_hw_context_switch_to((rt_uint32_t) & (tid->sp));
6783
}
6884

@@ -80,10 +96,15 @@ static void _signal_deliver(rt_thread_t tid)
8096
{
8197
rt_ubase_t level;
8298

99+
level = rt_hw_interrupt_disable();
100+
83101
/* thread is not interested in pended signals */
84-
if (!(tid->sig_pending & tid->sig_mask)) return;
102+
if (!(tid->sig_pending & tid->sig_mask))
103+
{
104+
rt_hw_interrupt_enable(level);
105+
return;
106+
}
85107

86-
level = rt_hw_interrupt_disable();
87108
if ((tid->stat & RT_THREAD_STAT_MASK) == RT_THREAD_SUSPEND)
88109
{
89110
/* resume thread to handle signal */
@@ -106,7 +127,7 @@ static void _signal_deliver(rt_thread_t tid)
106127
rt_hw_interrupt_enable(level);
107128

108129
/* do signal action in self thread context */
109-
rt_thread_handle_sig(RT_TRUE);
130+
rt_thread_handle_sig();
110131
}
111132
else if (!((tid->stat & RT_THREAD_STAT_SIGNAL_MASK) & RT_THREAD_STAT_SIGNAL))
112133
{
@@ -133,12 +154,13 @@ static void _signal_deliver(rt_thread_t tid)
133154

134155
rt_sighandler_t rt_signal_install(int signo, rt_sighandler_t handler)
135156
{
157+
rt_base_t level;
136158
rt_sighandler_t old = RT_NULL;
137159
rt_thread_t tid = rt_thread_self();
138160

139161
if (!sig_valid(signo)) return SIG_ERR;
140162

141-
rt_enter_critical();
163+
level = rt_hw_interrupt_disable();
142164
if (tid->sig_vectors == RT_NULL)
143165
{
144166
rt_thread_alloc_sig(tid);
@@ -152,7 +174,7 @@ rt_sighandler_t rt_signal_install(int signo, rt_sighandler_t handler)
152174
else if (handler == SIG_DFL) tid->sig_vectors[signo] = _signal_default_handler;
153175
else tid->sig_vectors[signo] = handler;
154176
}
155-
rt_exit_critical();
177+
rt_hw_interrupt_enable(level);
156178

157179
return old;
158180
}
@@ -270,7 +292,20 @@ int rt_signal_wait(const rt_sigset_t *set, rt_siginfo_t *si, rt_int32_t timeout)
270292

271293
LOG_D("sigwait: %d sig raised!", signo);
272294
if (si_prev) si_prev->list.next = si_node->list.next;
273-
else tid->si_list = si_node->list.next;
295+
else
296+
{
297+
struct siginfo_node *node_next;
298+
299+
if (si_node->list.next)
300+
{
301+
node_next = (void *)rt_slist_entry(si_node->list.next, struct siginfo_node, list);
302+
tid->si_list = node_next;
303+
}
304+
else
305+
{
306+
tid->si_list = RT_NULL;
307+
}
308+
}
274309

275310
/* clear pending */
276311
tid->sig_pending &= ~sig_mask(signo);
@@ -279,7 +314,14 @@ int rt_signal_wait(const rt_sigset_t *set, rt_siginfo_t *si, rt_int32_t timeout)
279314
}
280315

281316
si_prev = si_node;
282-
si_node = (void *)rt_slist_entry(si_node->list.next, struct siginfo_node, list);
317+
if (si_node->list.next)
318+
{
319+
si_node = (void *)rt_slist_entry(si_node->list.next, struct siginfo_node, list);
320+
}
321+
else
322+
{
323+
si_node = RT_NULL;
324+
}
283325
}
284326

285327
__done_int:
@@ -289,14 +331,15 @@ int rt_signal_wait(const rt_sigset_t *set, rt_siginfo_t *si, rt_int32_t timeout)
289331
return ret;
290332
}
291333

292-
void rt_thread_handle_sig(rt_bool_t clean_state)
334+
void rt_thread_handle_sig(void)
293335
{
294336
rt_base_t level;
295337

296338
rt_thread_t tid = rt_thread_self();
297339
struct siginfo_node *si_node;
298340

299341
level = rt_hw_interrupt_disable();
342+
300343
if (tid->sig_pending & tid->sig_mask)
301344
{
302345
/* if thread is not waiting for signal */
@@ -318,25 +361,24 @@ void rt_thread_handle_sig(rt_bool_t clean_state)
318361

319362
signo = si_node->si.si_signo;
320363
handler = tid->sig_vectors[signo];
364+
tid->sig_pending &= ~sig_mask(signo);
321365
rt_hw_interrupt_enable(level);
322366

323367
LOG_D("handle signal: %d, handler 0x%08x", signo, handler);
324368
if (handler) handler(signo);
325369

326370
level = rt_hw_interrupt_disable();
327-
tid->sig_pending &= ~sig_mask(signo);
328371
error = -RT_EINTR;
329372

330373
rt_mp_free(si_node); /* release this siginfo node */
331374
/* set errno in thread tcb */
332375
tid->error = error;
333376
}
334377

335-
/* whether clean signal status */
336-
if (clean_state == RT_TRUE) tid->stat &= ~RT_THREAD_STAT_SIGNAL;
378+
/* clean state */
379+
tid->stat &= ~RT_THREAD_STAT_SIGNAL;
337380
}
338381
}
339-
340382
rt_hw_interrupt_enable(level);
341383
}
342384

@@ -362,30 +404,30 @@ void rt_thread_alloc_sig(rt_thread_t tid)
362404
void rt_thread_free_sig(rt_thread_t tid)
363405
{
364406
rt_base_t level;
365-
struct siginfo_node *si_list;
407+
struct siginfo_node *si_node;
366408
rt_sighandler_t *sig_vectors;
367409

368410
level = rt_hw_interrupt_disable();
369-
si_list = (struct siginfo_node *)tid->si_list;
411+
si_node = (struct siginfo_node *)tid->si_list;
370412
tid->si_list = RT_NULL;
371413

372414
sig_vectors = tid->sig_vectors;
373415
tid->sig_vectors = RT_NULL;
374416
rt_hw_interrupt_enable(level);
375417

376-
if (si_list)
418+
if (si_node)
377419
{
378420
struct rt_slist_node *node;
379-
struct siginfo_node *si_node;
421+
struct rt_slist_node *node_to_free;
380422

381423
LOG_D("free signal info list");
382-
node = &(si_list->list);
424+
node = &(si_node->list);
383425
do
384426
{
385-
si_node = rt_slist_entry(node, struct siginfo_node, list);
386-
rt_mp_free(si_node);
387-
427+
node_to_free = node;
388428
node = node->next;
429+
si_node = rt_slist_entry(node_to_free, struct siginfo_node, list);
430+
rt_mp_free(si_node);
389431
} while (node);
390432
}
391433

@@ -416,30 +458,23 @@ int rt_thread_kill(rt_thread_t tid, int sig)
416458
struct rt_slist_node *node;
417459
struct siginfo_node *entry;
418460

419-
node = (struct rt_slist_node *)tid->si_list;
420-
rt_hw_interrupt_enable(level);
461+
si_node = (struct siginfo_node *)tid->si_list;
462+
if (si_node)
463+
node = (struct rt_slist_node *)&si_node->list;
464+
else
465+
node = RT_NULL;
421466

422467
/* update sig info */
423-
rt_enter_critical();
424468
for (; (node) != RT_NULL; node = node->next)
425469
{
426470
entry = rt_slist_entry(node, struct siginfo_node, list);
427471
if (entry->si.si_signo == sig)
428472
{
429473
memcpy(&(entry->si), &si, sizeof(siginfo_t));
430-
rt_exit_critical();
474+
rt_hw_interrupt_enable(level);
431475
return 0;
432476
}
433477
}
434-
rt_exit_critical();
435-
436-
/* disable interrupt to protect tcb */
437-
level = rt_hw_interrupt_disable();
438-
}
439-
else
440-
{
441-
/* a new signal */
442-
tid->sig_pending |= sig_mask(sig);
443478
}
444479
rt_hw_interrupt_enable(level);
445480

@@ -450,14 +485,22 @@ int rt_thread_kill(rt_thread_t tid, int sig)
450485
memcpy(&(si_node->si), &si, sizeof(siginfo_t));
451486

452487
level = rt_hw_interrupt_disable();
453-
if (!tid->si_list) tid->si_list = si_node;
454-
else
488+
489+
if (tid->si_list)
455490
{
456491
struct siginfo_node *si_list;
457492

458493
si_list = (struct siginfo_node *)tid->si_list;
459494
rt_slist_append(&(si_list->list), &(si_node->list));
460495
}
496+
else
497+
{
498+
tid->si_list = si_node;
499+
}
500+
501+
/* a new signal */
502+
tid->sig_pending |= sig_mask(sig);
503+
461504
rt_hw_interrupt_enable(level);
462505
}
463506
else

0 commit comments

Comments
 (0)