Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 31 additions & 10 deletions criu/timer.c
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,16 @@ static int encode_notify_thread_id(pid_t rtid, struct pstree_item *item, PosixTi

if (!(root_ns_mask & CLONE_NEWPID)) {
/* Non-pid-namespace case */
for (i = 0; i < item->nr_threads; i++) {
if (item->threads[i].real == rtid)
break;
}

if (i == item->nr_threads) {
pr_warn("Skipping timer because notify thread %d is dead\n", rtid);
return 1;
}

pte->notify_thread_id = rtid;
pte->has_notify_thread_id = true;
return 0;
Expand All @@ -326,8 +336,8 @@ static int encode_notify_thread_id(pid_t rtid, struct pstree_item *item, PosixTi
}

if (vtid == 0) {
pr_err("Unable to convert the notify thread id %d\n", rtid);
return -1;
pr_warn("Skipping timer because notify thread %d is dead\n", rtid);
return 1;
}

pte->notify_thread_id = vtid;
Expand All @@ -351,10 +361,7 @@ static int encode_posix_timer(struct pstree_item *item, struct posix_timer *v, s
pte->vsec = v->val.it_value.tv_sec;
pte->vnsec = v->val.it_value.tv_nsec;

if (encode_notify_thread_id(vp->spt.notify_thread_id, item, pte))
return -1;

return 0;
return encode_notify_thread_id(vp->spt.notify_thread_id, item, pte);
}

int parasite_dump_posix_timers_seized(struct proc_posix_timers_stat *proc_args, struct parasite_ctl *ctl,
Expand All @@ -367,7 +374,7 @@ int parasite_dump_posix_timers_seized(struct proc_posix_timers_stat *proc_args,
struct parasite_dump_posix_timers_args *args;
int ret, exit_code = -1;
int args_size;
int i;
int i, j;

if (core_alloc_posix_timers(tte, proc_args->timer_n, &pte))
return -1;
Expand All @@ -386,14 +393,28 @@ int parasite_dump_posix_timers_seized(struct proc_posix_timers_stat *proc_args,
if (ret < 0)
goto end_posix;

/*
* i advances every iteration (indexes parasite-filled args->timer[]);
* j advances only for timers we keep, both the next output slot
* and the final count. Timers whose notify thread has exited are
* skipped (i.e., j <= i).
*/
i = 0;
j = 0;
Comment thread
rst0git marked this conversation as resolved.
list_for_each_entry(temp, &proc_args->timers, list) {
posix_timer_entry__init(&pte[i]);
if (encode_posix_timer(item, &args->timer[i], temp, &pte[i]))
posix_timer_entry__init(&pte[j]);
ret = encode_posix_timer(item, &args->timer[i], temp, &pte[j]);
if (ret < 0)
goto end_posix;
tte->posix[i] = &pte[i];
if (ret == 1) {
i++;
continue;
}
tte->posix[j] = &pte[j];
i++;
j++;
}
tte->n_posix = j;

exit_code = 0;
end_posix:
Expand Down
2 changes: 2 additions & 0 deletions test/zdtm/static/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ TST_NOFILE := \
pthread_timers \
pthread_timers_h \
leader_posix_timer \
dead_thread_posix_timer \
rseq00 \
membarrier \
vdso00 \
Expand Down Expand Up @@ -618,6 +619,7 @@ pthread02: LDLIBS += -pthread
pthread_timers: LDLIBS += -lrt -pthread
pthread_timers_h: LDLIBS += -lrt -pthread
leader_posix_timer: LDLIBS += -lrt -pthread
dead_thread_posix_timer: LDLIBS += -lrt -pthread
different_creds: LDLIBS += -pthread
sigpending: LDLIBS += -pthread
sigaltstack: LDLIBS += -pthread
Expand Down
70 changes: 70 additions & 0 deletions test/zdtm/static/dead_thread_posix_timer.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#include <pthread.h>
#include <signal.h>
#include <sys/syscall.h>
#include <time.h>
#include <unistd.h>

#include "zdtmtst.h"

#ifndef SIGEV_THREAD_ID
#define SIGEV_THREAD_ID 4
#endif

const char *test_doc = "Check that a SIGEV_THREAD_ID timer targeting a dead thread doesn't break dump";
const char *test_author = "Felicitas Pojtinger <felicitaspojtinger@loopholelabs.io>";

static timer_t timerid;

static void *worker(void *arg)
{
pid_t tid;
struct sigevent evp = {};

tid = syscall(SYS_gettid);

evp.sigev_notify = SIGEV_THREAD_ID;
#ifdef __GLIBC__
evp._sigev_un._tid = tid;
#else
evp.sigev_notify_thread_id = tid;
#endif
evp.sigev_signo = SIGRTMIN;

if (timer_create(CLOCK_MONOTONIC, &evp, &timerid)) {
pr_perror("timer_create");
return (void *)1;
}

return NULL;
}

int main(int argc, char **argv)
{
pthread_t thr;
void *ret;

test_init(argc, argv);

if (pthread_create(&thr, NULL, worker, NULL)) {
pr_perror("pthread_create");
return 1;
}

if (pthread_join(thr, &ret)) {
pr_perror("pthread_join");
return 1;
}

if (ret != NULL) {
fail("Timer creation thread failed");
return 1;
}

test_daemon();
test_waitsig();

pass();

timer_delete(timerid);
return 0;
}
1 change: 1 addition & 0 deletions test/zdtm/static/dead_thread_posix_timer.desc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{'feature': 'ns_pid'}