waitid.cpp 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. /*
  2. * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/Variant.h>
  7. #include <Kernel/Debug.h>
  8. #include <Kernel/Process.h>
  9. namespace Kernel {
  10. KResultOr<siginfo_t> Process::do_waitid(Variant<Empty, NonnullRefPtr<Process>, NonnullRefPtr<ProcessGroup>> waitee, int options)
  11. {
  12. KResultOr<siginfo_t> result = KResult(KSuccess);
  13. if (Thread::current()->block<Thread::WaitBlocker>({}, options, move(waitee), result).was_interrupted())
  14. return EINTR;
  15. VERIFY(!result.is_error() || (options & WNOHANG) || result.error() != KSuccess);
  16. return result;
  17. }
  18. KResultOr<FlatPtr> Process::sys$waitid(Userspace<const Syscall::SC_waitid_params*> user_params)
  19. {
  20. VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this)
  21. REQUIRE_PROMISE(proc);
  22. Syscall::SC_waitid_params params;
  23. if (!copy_from_user(&params, user_params))
  24. return EFAULT;
  25. Variant<Empty, NonnullRefPtr<Process>, NonnullRefPtr<ProcessGroup>> waitee = Empty {};
  26. switch (params.idtype) {
  27. case P_ALL:
  28. waitee = Empty {};
  29. break;
  30. case P_PID: {
  31. auto waitee_process = Process::from_pid(params.id);
  32. if (!waitee_process || waitee_process->ppid() != Process::current().pid()) {
  33. return ECHILD;
  34. }
  35. waitee = waitee_process.release_nonnull();
  36. break;
  37. }
  38. case P_PGID: {
  39. auto waitee_group = ProcessGroup::from_pgid(params.id);
  40. if (!waitee_group) {
  41. return ECHILD;
  42. }
  43. waitee = waitee_group.release_nonnull();
  44. break;
  45. }
  46. default:
  47. return EINVAL;
  48. }
  49. dbgln_if(PROCESS_DEBUG, "sys$waitid({}, {}, {}, {})", params.idtype, params.id, params.infop, params.options);
  50. auto siginfo_or_error = do_waitid(move(waitee), params.options);
  51. if (siginfo_or_error.is_error())
  52. return siginfo_or_error.error();
  53. if (!copy_to_user(params.infop, &siginfo_or_error.value()))
  54. return EFAULT;
  55. return 0;
  56. }
  57. }