shim_exit.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. /* -*- mode:c; c-file-style:"k&r"; c-basic-offset: 4; tab-width:4; indent-tabs-mode:nil; mode:auto-fill; fill-column:78; -*- */
  2. /* vim: set ts=4 sw=4 et tw=78 fo=cqt wm=0: */
  3. /* Copyright (C) 2014 OSCAR lab, Stony Brook University
  4. This file is part of Graphene Library OS.
  5. Graphene Library OS is free software: you can redistribute it and/or
  6. modify it under the terms of the GNU General Public License
  7. as published by the Free Software Foundation, either version 3 of the
  8. License, or (at your option) any later version.
  9. Graphene Library OS is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program. If not, see <http://www.gnu.org/licenses/>. */
  15. /*
  16. * shim_exit.c
  17. *
  18. * Implementation of system call "exit" and "exit_group".
  19. */
  20. #include <shim_internal.h>
  21. #include <shim_table.h>
  22. #include <shim_thread.h>
  23. #include <shim_fs.h>
  24. #include <shim_handle.h>
  25. #include <shim_ipc.h>
  26. #include <shim_utils.h>
  27. #include <shim_checkpoint.h>
  28. #include <pal.h>
  29. #include <pal_error.h>
  30. #include <errno.h>
  31. #include <sys/syscall.h>
  32. #include <sys/mman.h>
  33. #include <asm/prctl.h>
  34. #include <linux/futex.h>
  35. void release_robust_list (struct robust_list_head * head);
  36. void release_clear_child_id (int * clear_child_tid);
  37. int thread_exit(struct shim_thread * self, bool send_ipc)
  38. {
  39. /* Chia-Che: Broadcast exit message as early as possible,
  40. so other process can start early on responding. */
  41. if (self->in_vm && send_ipc)
  42. ipc_cld_exit_send(self->ppid, self->tid, self->exit_code);
  43. lock(self->lock);
  44. if (!self->is_alive) {
  45. debug("thread %d is dead\n", self->tid);
  46. out:
  47. unlock(self->lock);
  48. return 0;
  49. }
  50. #ifdef PROFILE
  51. self->exit_time = GET_PROFILE_INTERVAL();
  52. #endif
  53. int exit_code = self->exit_code;
  54. self->is_alive = false;
  55. if (IS_INTERNAL(self))
  56. goto out;
  57. struct shim_handle_map * handle_map = self->handle_map;
  58. struct shim_handle * exec = self->exec;
  59. struct shim_thread * parent = self->parent;
  60. self->handle_map = NULL;
  61. self->exec = NULL;
  62. if (parent) {
  63. assert(parent != self);
  64. assert(parent->child_exit_event);
  65. debug("thread exits, notifying thread %d\n", parent->tid);
  66. lock(parent->lock);
  67. list_del_init(&self->siblings);
  68. list_add_tail(&self->siblings, &parent->exited_children);
  69. if (!self->in_vm) {
  70. debug("deliver SIGCHLD (thread = %d, exitval = %d)\n",
  71. self->tid, exit_code);
  72. siginfo_t info;
  73. memset(&info, 0, sizeof(siginfo_t));
  74. info.si_signo = SIGCHLD;
  75. info.si_pid = self->tid;
  76. info.si_uid = self->uid;
  77. info.si_status = (exit_code & 0xff) << 8;
  78. append_signal(parent, SIGCHLD, &info, true);
  79. }
  80. unlock(parent->lock);
  81. DkEventSet(parent->child_exit_event);
  82. } else {
  83. debug("parent not here, need to tell another process\n");
  84. ipc_cld_exit_send(self->ppid, self->tid, self->exit_code);
  85. }
  86. struct robust_list_head * robust_list = (void *) self->robust_list;
  87. self->robust_list = NULL;
  88. unlock(self->lock);
  89. if (handle_map)
  90. put_handle_map(handle_map);
  91. if (exec)
  92. put_handle(exec);
  93. if (robust_list)
  94. release_robust_list(robust_list);
  95. if (self->clear_child_tid)
  96. release_clear_child_id (self->clear_child_tid);
  97. DkEventSet(self->exit_event);
  98. return 0;
  99. }
  100. int try_process_exit (int error_code)
  101. {
  102. struct shim_thread * cur_thread = get_cur_thread();
  103. cur_thread->exit_code = -error_code;
  104. if (cur_thread->in_vm)
  105. thread_exit(cur_thread, true);
  106. if (check_last_thread(cur_thread))
  107. return 0;
  108. terminate_async_helper();
  109. if (!exit_with_ipc_helper(true))
  110. shim_clean();
  111. else
  112. DkThreadExit();
  113. return 0;
  114. }
  115. int shim_do_exit_group (int error_code)
  116. {
  117. INC_PROFILE_OCCURENCE(syscall_use_ipc);
  118. struct shim_thread * cur_thread = get_cur_thread();
  119. assert(!IS_INTERNAL(cur_thread));
  120. if (debug_handle)
  121. sysparser_printf("---- shim_exit_group (returning %d)\n", error_code);
  122. if (cur_thread->dummy) {
  123. thread_exit(cur_thread, true);
  124. switch_dummy_thread(cur_thread);
  125. }
  126. debug("now kill other threads in the process\n");
  127. do_kill_proc(cur_thread->tgid, cur_thread->tgid, SIGKILL, false);
  128. debug("now exit the process\n");
  129. try_process_exit(error_code);
  130. #ifdef PROFILE
  131. if (ENTER_TIME)
  132. SAVE_PROFILE_INTERVAL_SINCE(syscall_exit_group, ENTER_TIME);
  133. #endif
  134. DkThreadExit();
  135. return 0;
  136. }
  137. int shim_do_exit (int error_code)
  138. {
  139. INC_PROFILE_OCCURENCE(syscall_use_ipc);
  140. struct shim_thread * cur_thread = get_cur_thread();
  141. assert(!IS_INTERNAL(cur_thread));
  142. if (debug_handle)
  143. sysparser_printf("---- shim_exit (returning %d)\n", error_code);
  144. if (cur_thread->dummy) {
  145. thread_exit(cur_thread, true);
  146. switch_dummy_thread(cur_thread);
  147. }
  148. try_process_exit(error_code);
  149. #ifdef PROFILE
  150. if (ENTER_TIME)
  151. SAVE_PROFILE_INTERVAL_SINCE(syscall_exit, ENTER_TIME);
  152. #endif
  153. DkThreadExit();
  154. return 0;
  155. }