/* Process has exited but not been reaped so this must work. */
ASSERT_EQ(ioctl(self->child_pidfd1, PIDFD_GET_INFO, &info), 0);
info.mask = PIDFD_INFO_CGROUPID | PIDFD_INFO_EXIT;
ASSERT_EQ(ioctl(self->child_pidfd1, PIDFD_GET_INFO, &info), 0);
ASSERT_TRUE(!!(info.mask & PIDFD_INFO_CREDS)); /* Process has exited but not been reaped, so no PIDFD_INFO_EXIT information yet. */
ASSERT_FALSE(!!(info.mask & PIDFD_INFO_EXIT));
}
/* Process has already been reaped and PIDFD_INFO_EXIT hasn't been set. */
ASSERT_NE(ioctl(self->child_pidfd2, PIDFD_GET_INFO, &info), 0);
ASSERT_EQ(errno, ESRCH);
/* Process has exited but not been reaped so this must work. */
ASSERT_EQ(ioctl(self->child_pidfd3, PIDFD_GET_INFO, &info), 0);
info.mask = PIDFD_INFO_CGROUPID | PIDFD_INFO_EXIT;
ASSERT_EQ(ioctl(self->child_pidfd3, PIDFD_GET_INFO, &info), 0);
ASSERT_TRUE(!!(info.mask & PIDFD_INFO_CREDS)); /* Process has exited but not been reaped, so no PIDFD_INFO_EXIT information yet. */
ASSERT_FALSE(!!(info.mask & PIDFD_INFO_EXIT));
}
/* Process has already been reaped and PIDFD_INFO_EXIT hasn't been set. */
ASSERT_NE(ioctl(self->child_pidfd4, PIDFD_GET_INFO, &info), 0);
ASSERT_EQ(errno, ESRCH);
/* Inform the grand-parent what the tid of this thread is. */ if (write_nointr(ipc_socket, &pid_thread, sizeof(pid_thread)) != sizeof(pid_thread)) return NULL;
/* The thread will outlive the thread-group leader. */ if (pthread_create(&thread, NULL, pidfd_info_pause_thread, &ipc_sockets[1]))
syscall(__NR_exit, EXIT_FAILURE);
/* Make the thread-group leader exit prematurely. */
syscall(__NR_exit, EXIT_SUCCESS);
}
/* Retrieve the tid of the thread. */
EXPECT_EQ(close(ipc_sockets[1]), 0);
ASSERT_EQ(read_nointr(ipc_sockets[0], &pid_thread, sizeof(pid_thread)), sizeof(pid_thread));
EXPECT_EQ(close(ipc_sockets[0]), 0);
/* Opening a thread as a thread-group leader must fail. */
pidfd_thread = sys_pidfd_open(pid_thread, 0);
ASSERT_LT(pidfd_thread, 0);
ASSERT_EQ(errno, ENOENT);
/* Opening a thread as a PIDFD_THREAD must succeed. */
pidfd_thread = sys_pidfd_open(pid_thread, PIDFD_THREAD);
ASSERT_GE(pidfd_thread, 0);
/* Get PIDFD_GET_INFO using the thread-group leader pidfd. */
ASSERT_EQ(ioctl(pidfd_leader, PIDFD_GET_INFO, &info), 0);
ASSERT_TRUE(!!(info.mask & PIDFD_INFO_CREDS)); /* Process has exited but not been reaped, so no PIDFD_INFO_EXIT information yet. */
ASSERT_FALSE(!!(info.mask & PIDFD_INFO_EXIT));
ASSERT_EQ(info.pid, pid_leader);
/* *Nowretrievethesameinfousingthethreadspecificpidfd *forthethread-groupleader.
*/
info2.mask = PIDFD_INFO_CGROUPID | PIDFD_INFO_EXIT;
ASSERT_EQ(ioctl(pidfd_leader_thread, PIDFD_GET_INFO, &info2), 0);
ASSERT_TRUE(!!(info2.mask & PIDFD_INFO_CREDS)); /* Process has exited but not been reaped, so no PIDFD_INFO_EXIT information yet. */
ASSERT_FALSE(!!(info2.mask & PIDFD_INFO_EXIT));
ASSERT_EQ(info2.pid, pid_leader);
/* Now try the thread-specific pidfd. */
ASSERT_EQ(ioctl(pidfd_thread, PIDFD_GET_INFO, &info), 0);
ASSERT_TRUE(!!(info.mask & PIDFD_INFO_CREDS)); /* The thread hasn't exited, so no PIDFD_INFO_EXIT information yet. */
ASSERT_FALSE(!!(info.mask & PIDFD_INFO_EXIT));
ASSERT_EQ(info.pid, pid_thread);
fds.events = POLLIN;
fds.fd = pidfd_leader;
nevents = poll(&fds, 1, -1);
ASSERT_EQ(nevents, 1);
ASSERT_TRUE(!!(fds.revents & POLLIN)); /* The thread-group leader has been reaped. */
ASSERT_TRUE(!!(fds.revents & POLLHUP));
/* *Retrieveexitinformationforthethread-groupleaderviathe *thread-groupleaderpidfd.
*/
info.mask = PIDFD_INFO_CGROUPID | PIDFD_INFO_EXIT;
ASSERT_EQ(ioctl(pidfd_leader, PIDFD_GET_INFO, &info), 0);
ASSERT_FALSE(!!(info.mask & PIDFD_INFO_CREDS));
ASSERT_TRUE(!!(info.mask & PIDFD_INFO_EXIT)); /* Even though the thread-group exited successfully it will still report the group exit code. */
ASSERT_TRUE(WIFSIGNALED(info.exit_code));
ASSERT_EQ(WTERMSIG(info.exit_code), SIGKILL);
/* Even though the thread-group exited successfully it will still report the group exit code. */
ASSERT_TRUE(WIFSIGNALED(info2.exit_code));
ASSERT_EQ(WTERMSIG(info2.exit_code), SIGKILL);
/* Retrieve exit information for the thread. */
info.mask = PIDFD_INFO_CGROUPID | PIDFD_INFO_EXIT;
ASSERT_EQ(ioctl(pidfd_thread, PIDFD_GET_INFO, &info), 0);
ASSERT_FALSE(!!(info.mask & PIDFD_INFO_CREDS));
ASSERT_TRUE(!!(info.mask & PIDFD_INFO_EXIT));
/* The thread got SIGKILLed. */
ASSERT_TRUE(WIFSIGNALED(info.exit_code));
ASSERT_EQ(WTERMSIG(info.exit_code), SIGKILL);
/* Inform the grand-parent what the tid of this thread is. */ if (write_nointr(ipc_socket, &pid_thread, sizeof(pid_thread)) != sizeof(pid_thread)) return NULL;
if (read_nointr(ipc_socket, &pid_thread, sizeof(pid_thread)) != sizeof(pid_thread)) return NULL;
/* The thread will outlive the thread-group leader. */ if (pthread_create(&thread, NULL, pidfd_info_thread_exec, &ipc_sockets[1]))
syscall(__NR_exit, EXIT_FAILURE);
/* Make the thread-group leader exit prematurely. */
syscall(__NR_exit, EXIT_SUCCESS);
}
/* Open a thread-specific pidfd for the thread-group leader. */
pidfd_leader_thread = sys_pidfd_open(pid_leader, PIDFD_THREAD);
ASSERT_GE(pidfd_leader_thread, 0);
/* Retrieve the tid of the thread. */
EXPECT_EQ(close(ipc_sockets[1]), 0);
ASSERT_EQ(read_nointr(ipc_sockets[0], &pid_thread, sizeof(pid_thread)), sizeof(pid_thread));
/* Opening a thread as a PIDFD_THREAD must succeed. */
pidfd_thread = sys_pidfd_open(pid_thread, PIDFD_THREAD);
ASSERT_GE(pidfd_thread, 0);
/* Now that we've opened a thread-specific pidfd the thread can exec. */
ASSERT_EQ(write_nointr(ipc_sockets[0], &pid_thread, sizeof(pid_thread)), sizeof(pid_thread));
EXPECT_EQ(close(ipc_sockets[0]), 0);
ASSERT_EQ(wait_for_pid(pid_poller), 0);
/* Wait until the kernel has SIGKILLed the thread. */
fds.events = POLLHUP;
fds.fd = pidfd_thread;
nevents = poll(&fds, 1, -1);
ASSERT_EQ(nevents, 1); /* The thread has been reaped. */
ASSERT_TRUE(!!(fds.revents & POLLHUP));
/* Inform the grand-parent what the tid of this thread is. */ if (write_nointr(ipc_socket, &pid_thread, sizeof(pid_thread)) != sizeof(pid_thread)) return NULL;
if (read_nointr(ipc_socket, &pid_thread, sizeof(pid_thread)) != sizeof(pid_thread)) return NULL;
/* The thread will outlive the thread-group leader. */ if (pthread_create(&thread, NULL, pidfd_info_thread_exec_sane, &ipc_sockets[1]))
syscall(__NR_exit, EXIT_FAILURE);
/* Retrieve the tid of the thread. */
EXPECT_EQ(close(ipc_sockets[1]), 0);
ASSERT_EQ(read_nointr(ipc_sockets[0], &pid_thread, sizeof(pid_thread)), sizeof(pid_thread));
/* Opening a thread as a PIDFD_THREAD must succeed. */
pidfd_thread = sys_pidfd_open(pid_thread, PIDFD_THREAD);
ASSERT_GE(pidfd_thread, 0);
/* Open a thread-specific pidfd for the thread-group leader. */
pidfd_leader_thread = sys_pidfd_open(pid_leader, PIDFD_THREAD);
ASSERT_GE(pidfd_leader_thread, 0);
/* Now that we've opened a thread-specific pidfd the thread can exec. */
ASSERT_EQ(write_nointr(ipc_sockets[0], &pid_thread, sizeof(pid_thread)), sizeof(pid_thread));
EXPECT_EQ(close(ipc_sockets[0]), 0);
ASSERT_EQ(wait_for_pid(pid_poller), 0);
/* Wait until the kernel has SIGKILLed the thread. */
fds.events = POLLHUP;
fds.fd = pidfd_thread;
nevents = poll(&fds, 1, -1);
ASSERT_EQ(nevents, 1); /* The thread has been reaped. */
ASSERT_TRUE(!!(fds.revents & POLLHUP));
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.