sig_default.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562
  1. /****************************************************************************
  2. * sched/signal/sig_default.c
  3. *
  4. * Copyright (C) 2018 Gregory Nutt. All rights reserved.
  5. * Author: Gregory Nutt <gnutt@nuttx.org>
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. *
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. * 2. Redistributions in binary form must reproduce the above copyright
  14. * notice, this list of conditions and the following disclaimer in
  15. * the documentation and/or other materials provided with the
  16. * distribution.
  17. * 3. Neither the name NuttX nor the names of its contributors may be
  18. * used to endorse or promote products derived from this software
  19. * without specific prior written permission.
  20. *
  21. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  22. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  23. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  24. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  25. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  26. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  27. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  28. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  29. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  31. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  32. * POSSIBILITY OF SUCH DAMAGE.
  33. *
  34. ****************************************************************************/
  35. /****************************************************************************
  36. * Included Files
  37. ****************************************************************************/
  38. #include <nuttx/config.h>
  39. #include <sys/wait.h>
  40. #include <stdint.h>
  41. #include <stdlib.h>
  42. #include <string.h>
  43. #include <pthread.h>
  44. #include <signal.h>
  45. #include <assert.h>
  46. #include <nuttx/sched.h>
  47. #include <nuttx/irq.h>
  48. #include <nuttx/signal.h>
  49. #include "group/group.h"
  50. #include "sched/sched.h"
  51. #include "signal/signal.h"
  52. /****************************************************************************
  53. * Pre-processor Definitions
  54. ****************************************************************************/
  55. /* Bit definitions for the struct nxsig_defaction_s 'flags' field */
  56. #define SIG_FLAG_NOCATCH (1 << 0) /* Signal cannot be caught or ignored */
  57. /****************************************************************************
  58. * Private Types
  59. ****************************************************************************/
  60. /* This type provides the default action associated with a signal */
  61. struct nxsig_defaction_s
  62. {
  63. uint8_t signo; /* Signal number. Range 1..MAX_SIGNO */
  64. uint8_t flags; /* See SIG_FLAG_ definitions */
  65. _sa_handler_t action; /* Default signal action */
  66. };
  67. /****************************************************************************
  68. * Private Function Prototypes
  69. ****************************************************************************/
  70. /* Default actions */
  71. static void nxsig_null_action(int signo);
  72. static void nxsig_abnormal_termination(int signo);
  73. static void nxsig_stop_task(int signo);
  74. /* Helpers */
  75. static _sa_handler_t nxsig_default_action(int signo);
  76. static void nxsig_setup_default_action(FAR struct task_group_s *group,
  77. FAR const struct nxsig_defaction_s *info);
  78. /****************************************************************************
  79. * Private Data
  80. ****************************************************************************/
  81. /* NOTE: Default actions are not currently supported for very many signals.
  82. * However, this array is set up to support an indefinite number of default
  83. * signal actions.
  84. */
  85. /* This table is used to make the default action for a signal to the correct
  86. * signal handler. Signals whose default action is be ignored do not need
  87. * to be in this table (e.g., SIGCHLD).
  88. */
  89. static const struct nxsig_defaction_s g_defactions[] =
  90. {
  91. #ifdef CONFIG_SIG_SIGUSR1_ACTION
  92. { SIGUSR1, 0, nxsig_abnormal_termination },
  93. #endif
  94. #ifdef CONFIG_SIG_SIGUSR2_ACTION
  95. { SIGUSR2, 0, nxsig_abnormal_termination },
  96. #endif
  97. #ifdef CONFIG_SIG_SIGALRM_ACTION
  98. { SIGALRM, 0, nxsig_abnormal_termination },
  99. #endif
  100. #ifdef CONFIG_SIG_SIGPOLL_ACTION
  101. { SIGPOLL, 0, nxsig_abnormal_termination },
  102. #endif
  103. #ifdef CONFIG_SIG_SIGSTOP_ACTION
  104. { SIGSTOP, SIG_FLAG_NOCATCH, nxsig_stop_task },
  105. { SIGSTP, 0, nxsig_stop_task },
  106. { SIGCONT, SIG_FLAG_NOCATCH, nxsig_null_action },
  107. #endif
  108. #ifdef CONFIG_SIG_SIGKILL_ACTION
  109. { SIGINT, 0, nxsig_abnormal_termination },
  110. { SIGKILL, SIG_FLAG_NOCATCH, nxsig_abnormal_termination }
  111. #endif
  112. };
  113. #define NACTIONS (sizeof(g_defactions) / sizeof(struct nxsig_defaction_s))
  114. /****************************************************************************
  115. * Private Functions
  116. ****************************************************************************/
  117. /* TODO: Take into account pthread-specific signal behaviors */
  118. /* Default Actions:
  119. *
  120. * - Abnormal termination of the process. The process is terminated with
  121. * all the consequences of _exit() except that the status made available
  122. * to wait() and waitpid() indicates abnormal termination by the
  123. * specified signal.
  124. * - Abnormal termination of the process. Additionally with the XSI
  125. * extension, implementation-defined abnormal termination actions, such
  126. * as creation of a core file, may occur.
  127. * - Ignore the signal.
  128. * - Stop the process.
  129. * - Continue the process, if it is stopped; otherwise, ignore the signal.
  130. */
  131. /****************************************************************************
  132. * Name: nxsig_null_action
  133. *
  134. * Description:
  135. * The do-nothing default signal action handler.
  136. *
  137. * Input Parameters:
  138. * Standard signal handler parameters
  139. *
  140. * Returned Value:
  141. * None
  142. *
  143. ****************************************************************************/
  144. static void nxsig_null_action(int signo)
  145. {
  146. }
  147. /****************************************************************************
  148. * Name: nxsig_abnormal_termination
  149. *
  150. * Description:
  151. * This is the handler for the abnormal termination default action.
  152. *
  153. * Input Parameters:
  154. * Standard signal handler parameters
  155. *
  156. * Returned Value:
  157. * None
  158. *
  159. ****************************************************************************/
  160. static void nxsig_abnormal_termination(int signo)
  161. {
  162. FAR struct tcb_s *rtcb = (FAR struct tcb_s *)this_task();
  163. /* Careful: In the multi-threaded task, the signal may be handled on a
  164. * child pthread.
  165. */
  166. #ifdef HAVE_GROUP_MEMBERS
  167. /* Kill of of the children of the task. This will not kill the currently
  168. * running task/pthread (this_task). It will kill the main thread of the
  169. * task group if the this_task is a
  170. * pthread.
  171. */
  172. group_killchildren((FAR struct task_tcb_s *)rtcb);
  173. #endif
  174. #ifndef CONFIG_DISABLE_PTHREAD
  175. /* Check if the currently running task is actually a pthread */
  176. if ((rtcb->flags & TCB_FLAG_TTYPE_MASK) == TCB_FLAG_TTYPE_PTHREAD)
  177. {
  178. /* Exit the final thread of the task group.
  179. *
  180. * REVISIT: This will not work if HAVE_GROUP_MEMBERS is not set.
  181. */
  182. pthread_exit(NULL);
  183. }
  184. else
  185. #endif
  186. {
  187. /* Exit to terminate the task (note that exit() vs. _exit() is used. */
  188. exit(EXIT_FAILURE);
  189. }
  190. }
  191. /****************************************************************************
  192. * Name: nxsig_stop_task
  193. *
  194. * Description:
  195. * This is the handler for the abnormal termination default action.
  196. *
  197. * Input Parameters:
  198. * Standard signal handler parameters
  199. *
  200. * Returned Value:
  201. * None
  202. *
  203. ****************************************************************************/
  204. static void nxsig_stop_task(int signo)
  205. {
  206. FAR struct tcb_s *rtcb = (FAR struct tcb_s *)this_task();
  207. #if defined(CONFIG_SCHED_WAITPID) && !defined(CONFIG_SCHED_HAVE_PARENT)
  208. FAR struct task_group_s *group;
  209. DEBUGASSERT(rtcb != NULL && rtcb->group != NULL);
  210. group = rtcb->group;
  211. #endif
  212. /* Careful: In the multi-threaded task, the signal may be handled on a
  213. * child pthread.
  214. */
  215. #ifdef HAVE_GROUP_MEMBERS
  216. /* Suspend of of the children of the task. This will not suspend the
  217. * currently running task/pthread (this_task). It will suspend the
  218. * main thread of the task group if the this_task is a pthread.
  219. */
  220. group_suspendchildren(rtcb);
  221. #endif
  222. /* Lock the scheduler so this thread is not pre-empted until after we
  223. * call sched_suspend().
  224. */
  225. sched_lock();
  226. #if defined(CONFIG_SCHED_WAITPID) && !defined(CONFIG_SCHED_HAVE_PARENT)
  227. /* Notify via waitpid if any parent is waiting for this task to EXIT
  228. * or STOP. This action is only performed if WUNTRACED is set in the
  229. * waitpid flags.
  230. */
  231. if ((group->tg_waitflags & WUNTRACED) != 0)
  232. {
  233. /* Return zero for exit status (we are not exiting, however) */
  234. if (group->tg_statloc != NULL)
  235. {
  236. *group->tg_statloc = 0;
  237. group->tg_statloc = NULL;
  238. }
  239. /* tg_waitflags == 0 means that the flags are available to another
  240. * caller of waitpid().
  241. */
  242. group->tg_waitflags = 0;
  243. /* YWakeup any tasks waiting for this task to exit or stop. */
  244. while (group->tg_exitsem.semcount < 0)
  245. {
  246. /* Wake up the thread */
  247. nxsem_post(&group->tg_exitsem);
  248. }
  249. }
  250. #endif
  251. /* Then, finally, suspend this the final thread of the task group */
  252. sched_suspend(rtcb);
  253. sched_unlock();
  254. }
  255. /****************************************************************************
  256. * Name: nxsig_default_action
  257. *
  258. * Description:
  259. * Look up the default action associated with this signal
  260. *
  261. * Input Parameters:
  262. * signo - The signal number to use in the query
  263. *
  264. * Returned Value:
  265. * The default handler associated with this signal
  266. *
  267. ****************************************************************************/
  268. static _sa_handler_t nxsig_default_action(int signo)
  269. {
  270. int i;
  271. /* Search the default action table for the entry associated with this
  272. * signal.
  273. */
  274. for (i = 0; i < NACTIONS; i++)
  275. {
  276. if (g_defactions[i].signo == signo)
  277. {
  278. return g_defactions[i].action;
  279. }
  280. }
  281. /* No default action */
  282. return SIG_IGN;
  283. }
  284. /****************************************************************************
  285. * Name: nxsig_setup_default_action
  286. *
  287. * Description:
  288. * Setup the default action for a signal.
  289. *
  290. * This function is called early in task setup, prior to the creation of
  291. * any pthreads so we should have exclusive access to the group structure.
  292. *
  293. * Input Parameters:
  294. * group - The group that the task belongs in.
  295. * action - The new default signal action
  296. * signo - The signal that will produce this default action
  297. *
  298. * Returned Value:
  299. * None
  300. *
  301. ****************************************************************************/
  302. static void nxsig_setup_default_action(FAR struct task_group_s *group,
  303. FAR const struct nxsig_defaction_s *info)
  304. {
  305. /* Get the address of the handler for this signals default action. */
  306. if (info->action != SIG_IGN)
  307. {
  308. struct sigaction sa;
  309. /* Attach the signal handler.
  310. *
  311. * NOTE: nxsig_action will call nxsig_default(tcb, action, false).
  312. * Don't be surprised.
  313. */
  314. memset(&sa, 0, sizeof(sa));
  315. sa.sa_handler = info->action;
  316. sa.sa_flags = SA_SIGINFO;
  317. (void)nxsig_action(info->signo, &sa, NULL, true);
  318. /* Indicate that the default signal handler has been attached */
  319. (void)sigaddset(&group->tg_sigdefault, (int)info->signo);
  320. }
  321. }
  322. /****************************************************************************
  323. * Public Functions
  324. ****************************************************************************/
  325. /****************************************************************************
  326. * Name: nxsig_isdefault
  327. *
  328. * Description:
  329. * Return true if the specified signal is set to the default action.
  330. *
  331. * Input Parameters:
  332. * tcb - Identifies the thread associated with the default handler
  333. * signo - The signal number to be queried
  334. *
  335. * Returned Value:
  336. * Zero (OK) is returned on success; A negated errno value is returned
  337. * on failure.
  338. *
  339. ****************************************************************************/
  340. bool nxsig_isdefault(FAR struct tcb_s *tcb, int signo)
  341. {
  342. FAR struct task_group_s *group;
  343. int ret;
  344. DEBUGASSERT(tcb != NULL && tcb->group != NULL && GOOD_SIGNO(signo));
  345. group = tcb->group;
  346. /* Return true if the signo is marked as using the default action. Return
  347. * false in all other cases.
  348. */
  349. ret = sigismember(&group->tg_sigdefault, signo);
  350. return ret < 0 ? false : (bool)ret;
  351. }
  352. /****************************************************************************
  353. * Name: nxsig_iscatchable
  354. *
  355. * Description:
  356. * Return true if the specified signal can be caught or ignored.
  357. *
  358. * Input Parameters:
  359. * signo - The signal number to be queried
  360. *
  361. * Returned Value:
  362. * Zero (OK) is returned on success; A negated errno value is returned
  363. * on failure.
  364. *
  365. ****************************************************************************/
  366. bool nxsig_iscatchable(int signo)
  367. {
  368. int i;
  369. /* Search the default action table for the entry associated with this
  370. * signal.
  371. */
  372. for (i = 0; i < NACTIONS; i++)
  373. {
  374. if (g_defactions[i].signo == signo)
  375. {
  376. return (g_defactions[i].flags & SIG_FLAG_NOCATCH) == 0;
  377. }
  378. }
  379. /* If it is not in the table, then it is catchable */
  380. return true;
  381. }
  382. /****************************************************************************
  383. * Name: nxsig_default
  384. *
  385. * Description:
  386. * If 'defaction' is true, then return the default signal handler action
  387. * for the specified signal and mark that the default signal hander is
  388. * in place (it is not yet).
  389. *
  390. * If 'defaction' is false, then mark that the default signal handler is
  391. * NOT in place and return SIG_IGN.
  392. *
  393. * This function is called form sigaction() to handle actions = SIG_DFL.
  394. *
  395. * Input Parameters:
  396. * tcb - Identifies the thread associated with the default handler
  397. * signo - The signal number whose behavior will be modified.
  398. * defaction - True: the default action is in place
  399. *
  400. * Returned Value:
  401. * The address of the default signal action handler is returne on success.
  402. * SIG_IGN is returned if there is no default action.
  403. *
  404. ****************************************************************************/
  405. _sa_handler_t nxsig_default(FAR struct tcb_s *tcb, int signo, bool defaction)
  406. {
  407. FAR struct task_group_s *group;
  408. _sa_handler_t handler = SIG_IGN;
  409. irqstate_t flags;
  410. DEBUGASSERT(tcb != NULL && tcb->group != NULL);
  411. group = tcb->group;
  412. /* Are we setting or unsetting the default action? */
  413. if (defaction)
  414. {
  415. /* We are setting the default action. Look up the default action
  416. * associated with signo.
  417. */
  418. handler = nxsig_default_action(signo);
  419. if (handler != SIG_IGN)
  420. {
  421. /* sigaddset() is not atomic (but neither is sigaction()) */
  422. flags = spin_lock_irqsave();
  423. (void)sigaddset(&group->tg_sigdefault, signo);
  424. spin_unlock_irqrestore(flags);
  425. }
  426. }
  427. if (handler == SIG_IGN)
  428. {
  429. /* We are unsetting the default action */
  430. /* sigdelset() is not atomic (but neither is sigaction()) */
  431. flags = spin_lock_irqsave();
  432. (void)sigdelset(&group->tg_sigdefault, signo);
  433. spin_unlock_irqrestore(flags);
  434. }
  435. return handler;
  436. }
  437. /****************************************************************************
  438. * Name: nxsig_default_initialize
  439. *
  440. * Description:
  441. * Set all signals to their default action. This is called from nxtask_start
  442. * to configure the newly started task.
  443. *
  444. * Input Parameters:
  445. * tcb - Identifies the thread associated with the default handlers
  446. *
  447. * Returned Value:
  448. * Zero (OK) is returned on success; A negated errno value is returned
  449. * on failure.
  450. *
  451. ****************************************************************************/
  452. int nxsig_default_initialize(FAR struct tcb_s *tcb)
  453. {
  454. FAR struct task_group_s *group;
  455. int i;
  456. DEBUGASSERT(tcb != NULL && tcb->group != NULL);
  457. group = tcb->group;
  458. /* Initialize the set of default signal handlers */
  459. (void)sigemptyset(&group->tg_sigdefault);
  460. /* Setup the default action for each signal in g_defactions[] */
  461. for (i = 0; i < NACTIONS; i++)
  462. {
  463. nxsig_setup_default_action(group, &g_defactions[i]);
  464. }
  465. return OK;
  466. }