Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

429 lines
8.3 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. sigapi.c
  5. Abstract:
  6. This module implements all signal oriented APIs.
  7. Author:
  8. Mark Lucovsky (markl) 30-Mar-1989
  9. Revision History:
  10. --*/
  11. #include "psxsrv.h"
  12. BOOLEAN
  13. PsxSigAction (
  14. IN PPSX_PROCESS p,
  15. IN OUT PPSX_API_MSG m
  16. )
  17. /*++
  18. Routine Description:
  19. This procedure implements POSIX sigaction
  20. Arguments:
  21. p - Supplies the address of the process making the call.
  22. m - Supplies the address of the message associated with the open request.
  23. Return Value:
  24. TRUE - The contens of *m should be used to generate a reply.
  25. --*/
  26. {
  27. PPSX_SIGACTION_MSG args;
  28. args = &m->u.SigAction;
  29. //
  30. // Validate Signal
  31. //
  32. if ( !ISSIGNOINRANGE(args->Sig) || args->Sig <= 0 ) {
  33. m->Error = EINVAL;
  34. return TRUE;
  35. }
  36. if (ARGUMENT_PRESENT(args->ActSpecified) ) {
  37. //
  38. // Since call is attempting to set a signal action, fail if:
  39. // attemping to catch a signal that cant be caught
  40. // SIGKILL, SIGSTOP
  41. // attemping to ignore a signal that cant be ignored
  42. // SIGKILL, SIGSTOP
  43. //
  44. // SIGKILL and SIGSTOP can only be set to SIG_DFL !
  45. //
  46. if ( ((args->Sig == SIGKILL) || (args->Sig == SIGSTOP)) &&
  47. (args->Act.sa_handler != (_handler) SIG_DFL) ) {
  48. m->Error = EINVAL;
  49. return TRUE;
  50. } else {
  51. //
  52. // Clear SIGKILL and SIGSTOP from the new block
  53. // mask without causing an error
  54. //
  55. SIGDELSET(&args->Act.sa_mask, SIGKILL);
  56. SIGDELSET(&args->Act.sa_mask, SIGSTOP);
  57. args->Act.sa_mask &= _SIGFULLSET;
  58. AcquireProcessLock(p);
  59. args->Oact = p->SignalDataBase.SignalDisposition[args->Sig-1];
  60. p->SignalDataBase.SignalDisposition[args->Sig-1] = args->Act;
  61. if (SIGISMEMBER(&p->SignalDataBase.PendingSignalMask, args->Sig) ) {
  62. //
  63. // Signal whose action is being changed is pending.
  64. //
  65. // If signal iction is being set to ignored, or if being set to
  66. // default action, and default action is to ignore the signal,
  67. // then clear the signal from the set of pending signals.
  68. //
  69. if ( (args->Act.sa_handler == SIG_IGN) ||
  70. ((args->Act.sa_handler == SIG_DFL) && (args->Sig == SIGCHLD)) ) {
  71. SIGDELSET(&p->SignalDataBase.PendingSignalMask, args->Sig);
  72. }
  73. }
  74. ReleaseProcessLock(p);
  75. }
  76. } else {
  77. AcquireProcessLock(p);
  78. args->Oact = p->SignalDataBase.SignalDisposition[args->Sig-1];
  79. ReleaseProcessLock(p);
  80. }
  81. return TRUE;
  82. }
  83. BOOLEAN
  84. PsxSigProcMask(
  85. IN PPSX_PROCESS p,
  86. IN PPSX_API_MSG m
  87. )
  88. /*++
  89. Routine Description:
  90. This procedure implements POSIX sigaction
  91. Arguments:
  92. p - Supplies the address of the process making the call.
  93. m - Supplies the address of the message associated with the open request.
  94. Return Value:
  95. TRUE - The contens of *m should be used to generate a reply.
  96. --*/
  97. {
  98. PPSX_SIGPROCMASK_MSG args;
  99. args = &m->u.SigProcMask;
  100. AcquireProcessLock(p);
  101. args->Oset = p->SignalDataBase.BlockedSignalMask;
  102. if ( ARGUMENT_PRESENT(args->SetSpecified) ) {
  103. switch (args->How) {
  104. case SIG_BLOCK:
  105. p->SignalDataBase.BlockedSignalMask |= args->Set;
  106. break;
  107. case SIG_UNBLOCK:
  108. p->SignalDataBase.BlockedSignalMask &= ~args->Set;
  109. break;
  110. case SIG_SETMASK:
  111. p->SignalDataBase.BlockedSignalMask = args->Set;
  112. break;
  113. default:
  114. m->Error = EINVAL;
  115. ReleaseProcessLock(p);
  116. return TRUE;
  117. }
  118. SIGDELSET(&p->SignalDataBase.BlockedSignalMask,SIGKILL);
  119. SIGDELSET(&p->SignalDataBase.BlockedSignalMask,SIGSTOP);
  120. }
  121. ReleaseProcessLock(p);
  122. return TRUE;
  123. }
  124. BOOLEAN
  125. PsxSigPending(
  126. IN PPSX_PROCESS p,
  127. IN PPSX_API_MSG m
  128. )
  129. {
  130. PPSX_SIGPENDING_MSG args;
  131. args = &m->u.SigPending;
  132. args->Set = p->SignalDataBase.PendingSignalMask;
  133. m->Error = 0;
  134. return TRUE;
  135. }
  136. BOOLEAN
  137. PsxSigSuspend(
  138. IN PPSX_PROCESS p,
  139. IN PPSX_API_MSG m
  140. )
  141. /*++
  142. Routine Description:
  143. This procedure implements POSIX sigsuspend
  144. Arguments:
  145. p - Supplies the address of the process making the call.
  146. m - Supplies the address of the message associated with the request.
  147. Return Value:
  148. FALSE - A reply will not be generated until a signal is generated that
  149. either terminates the process or is delivered to the process.
  150. --*/
  151. {
  152. PPSX_SIGSUSPEND_MSG args;
  153. sigset_t NewBlockMask;
  154. NTSTATUS Status;
  155. args = &m->u.SigSuspend;
  156. AcquireProcessLock(p);
  157. NewBlockMask = p->SignalDataBase.BlockedSignalMask;
  158. //
  159. // For sigsuspend, sigmask is specified; otherwise, the current
  160. // blocked signal mask is used
  161. //
  162. if ( args->SigMaskSpecified ) {
  163. p->SignalDataBase.BlockedSignalMask = args->SigMask;
  164. }
  165. SIGDELSET(&p->SignalDataBase.BlockedSignalMask,SIGKILL);
  166. SIGDELSET(&p->SignalDataBase.BlockedSignalMask,SIGSTOP);
  167. ReleaseProcessLock(p);
  168. Status = BlockProcess(p, (PVOID)NewBlockMask, PsxSigSuspendHandler,
  169. m, FALSE, NULL);
  170. if (!NT_SUCCESS(Status)) {
  171. m->Error = PsxStatusToErrno(Status);
  172. return TRUE;
  173. }
  174. //
  175. // The process was blocked -- don't reply to the api request yet.
  176. //
  177. return FALSE;
  178. }
  179. BOOLEAN
  180. PsxNull (
  181. IN PPSX_PROCESS p,
  182. IN OUT PPSX_API_MSG m
  183. )
  184. /*++
  185. Routine Description:
  186. The null system service. This service is used to get a process to
  187. look at its pending signals.
  188. Arguments:
  189. p - Supplies the address of the process making the call.
  190. m - Supplies the address of the message associated with the request.
  191. Return Value:
  192. TRUE - The contens of *m should be used to generate a reply.
  193. --*/
  194. {
  195. //
  196. // The process may fork again.
  197. //
  198. p->Flags &= ~P_NO_FORK;
  199. return TRUE;
  200. }
  201. BOOLEAN
  202. PsxKill(
  203. IN PPSX_PROCESS p,
  204. IN PPSX_API_MSG m
  205. )
  206. /*++
  207. Routine Description:
  208. This function implements posix kill().
  209. Arguments:
  210. p - Supplies the address of the calling process
  211. m - Supplies the address of the related message
  212. Return Value:
  213. TRUE - Always succeeds and generates a reply
  214. --*/
  215. {
  216. PPSX_KILL_MSG args;
  217. PPSX_PROCESS cp;
  218. BOOLEAN SignalSent;
  219. pid_t TargetGroup;
  220. args = &m->u.Kill;
  221. if ( ! ISSIGNOINRANGE(args->Sig) ) {
  222. m->Error = EINVAL;
  223. return TRUE;
  224. }
  225. if ( args->Pid < 0 && args->Pid != -1 ) {
  226. TargetGroup = args->Pid * -1;
  227. } else {
  228. TargetGroup = 0;
  229. }
  230. SignalSent = FALSE;
  231. //
  232. // Lock the process table so that we can scan process table.
  233. //
  234. AcquireProcessStructureLock();
  235. //
  236. // Scan process table looking for pid
  237. //
  238. for (cp = FirstProcess; cp < LastProcess; cp++) {
  239. //
  240. // Only look at non-free slots
  241. //
  242. if (cp->Flags & P_FREE) {
  243. continue;
  244. }
  245. if (args->Pid > 0) {
  246. //
  247. // Send signal to process whose Pid is args->Pid
  248. //
  249. if (cp->Pid == args->Pid) {
  250. PsxSignalProcess(cp, args->Sig);
  251. SignalSent = TRUE;
  252. }
  253. }
  254. if (args->Pid == 0) {
  255. //
  256. // Send signal to all processes whose process group id
  257. // matches the caller
  258. //
  259. if (cp->ProcessGroupId == p->ProcessGroupId) {
  260. PsxSignalProcess(cp, args->Sig);
  261. SignalSent = TRUE;
  262. }
  263. }
  264. if (args->Pid == -1) {
  265. //
  266. // Posix does not define this.
  267. //
  268. continue;
  269. }
  270. if (TargetGroup) {
  271. //
  272. // Send signal to all processes whose process group id
  273. // matches the absolute value of args->Pid
  274. //
  275. if ( cp->ProcessGroupId == TargetGroup ) {
  276. PsxSignalProcess(cp, args->Sig);
  277. SignalSent = TRUE;
  278. }
  279. }
  280. }
  281. if (!SignalSent) {
  282. m->Error = ESRCH;
  283. }
  284. ReleaseProcessStructureLock();
  285. return TRUE;
  286. }