Message ID | 1552978181-27748-4-git-send-email-sumit.garg@linaro.org |
---|---|
State | New |
Headers | show |
Series | syscalls: add tgkill test-cases | expand |
Hi! I've added one more ESRCH case here: diff --git a/testcases/kernel/syscalls/tgkill/tgkill03.c b/testcases/kernel/syscalls/tgkill/tgkill03.c index b78e9d95a..f5bbdc5a8 100644 --- a/testcases/kernel/syscalls/tgkill/tgkill03.c +++ b/testcases/kernel/syscalls/tgkill/tgkill03.c @@ -76,7 +76,8 @@ static const struct testcase { { "Invalid tgid", &invalid_pid, &parent_tid, SIGUSR1, EINVAL }, { "Invalid tid", &parent_tgid, &invalid_pid, SIGUSR1, EINVAL }, { "Invalid signal", &parent_tgid, &parent_tid, -1, EINVAL }, - { "Defunct thread ID", &parent_tgid, &defunct_tid, SIGUSR1, ESRCH }, + { "Defunct tid", &parent_tgid, &defunct_tid, SIGUSR1, ESRCH }, + { "Defunct tgid", &defunct_tid, &child_tid, SIGUSR1, ESRCH }, { "Valid tgkill call", &parent_tgid, &child_tid, SIGUSR1, 0 }, };
----- Original Message ----- > +static void setup(void) > +{ > + sigset_t sigusr1; > + pthread_t defunct_thread; > + > + sigemptyset(&sigusr1); > + sigaddset(&sigusr1, SIGUSR1); > + pthread_sigmask(SIG_BLOCK, &sigusr1, NULL); > + > + parent_tgid = getpid(); > + parent_tid = sys_gettid(); > + > + SAFE_PTHREAD_CREATE(&child_thread, NULL, child_thread_func, NULL); > + > + TST_CHECKPOINT_WAIT(0); I'm seeing reports of this test failing on s390x: st_test.c:1096: INFO: Timeout per run is 0h 05m 00s tgkill03.c:92: PASS: Invalid tgid failed as expected: EINVAL tgkill03.c:92: PASS: Invalid tid failed as expected: EINVAL tgkill03.c:92: PASS: Invalid signal failed as expected: EINVAL tgkill03.c:96: FAIL: Defunct tid should have failed with ESRCH: SUCCESS tgkill03.c:92: PASS: Defunct tgid failed as expected: ESRCH tgkill03.c:99: PASS: Valid tgkill call succeeded and I suspect this piece: > + > + SAFE_PTHREAD_CREATE(&defunct_thread, NULL, defunct_thread_func, NULL); > + > + SAFE_PTHREAD_JOIN(defunct_thread, NULL); > +} glibc pthread_join() waits for CLONE_CHILD_CLEARTID to clear tid, and then resumes. Which kernel does at: do_exit exit_mm mm_release put_user(0, tsk->clear_child_tid); so there's still work to be done after that, and I suspect tid is still valid while that happens. My first idea: wait until /proc/pid/task/<tid> disappears. Regards, Jan
On Sun, Jun 16, 2019 at 7:08 AM Jan Stancek <jstancek@redhat.com> wrote: > > ----- Original Message ----- > > +static void setup(void) > > +{ > > + sigset_t sigusr1; > > + pthread_t defunct_thread; > > + > > + sigemptyset(&sigusr1); > > + sigaddset(&sigusr1, SIGUSR1); > > + pthread_sigmask(SIG_BLOCK, &sigusr1, NULL); > > + > > + parent_tgid = getpid(); > > + parent_tid = sys_gettid(); > > + > > + SAFE_PTHREAD_CREATE(&child_thread, NULL, child_thread_func, NULL); > > + > > + TST_CHECKPOINT_WAIT(0); > > I'm seeing reports of this test failing on s390x: > > st_test.c:1096: INFO: Timeout per run is 0h 05m 00s > tgkill03.c:92: PASS: Invalid tgid failed as expected: EINVAL > tgkill03.c:92: PASS: Invalid tid failed as expected: EINVAL > tgkill03.c:92: PASS: Invalid signal failed as expected: EINVAL > tgkill03.c:96: FAIL: Defunct tid should have failed with ESRCH: SUCCESS > tgkill03.c:92: PASS: Defunct tgid failed as expected: ESRCH > tgkill03.c:99: PASS: Valid tgkill call succeeded > > and I suspect this piece: > > > + > > + SAFE_PTHREAD_CREATE(&defunct_thread, NULL, defunct_thread_func, > NULL); > > + > > + SAFE_PTHREAD_JOIN(defunct_thread, NULL); > > +} > > glibc pthread_join() waits for CLONE_CHILD_CLEARTID to clear tid, > and then resumes. Which kernel does at: > do_exit > exit_mm > mm_release > put_user(0, tsk->clear_child_tid); > > so there's still work to be done after that, and I suspect tid is still > valid > while that happens. > > My first idea: wait until /proc/pid/task/<tid> disappears. > The anaysis is probably right, but this idea doesn't work for me. Seems /proc/pid/task/<tid> is not the key point to confirm that tid has been clear. I just have a try as below: =========== # for i in `seq 1000`; do echo "i = $i" && ./tgkill03 || break; done ... i = 96 tst_test.c:1112: INFO: Timeout per run is 0h 05m 00s tgkill03.c:106: FAIL: Defunct tid should have failed with ESRCH: SUCCESS =========== --- a/testcases/kernel/syscalls/tgkill/tgkill03.c +++ b/testcases/kernel/syscalls/tgkill/tgkill03.c @@ -5,6 +5,7 @@ * Test simple tgkill() error cases. */ +#include <stdio.h> #include <pthread.h> #include <pwd.h> #include <sys/types.h> @@ -19,6 +20,7 @@ static pid_t parent_tgid; static pid_t parent_tid; static pid_t child_tid; static pid_t defunct_tid; +char buf[1024]; static const int invalid_pid = -1; @@ -35,6 +37,8 @@ static void *defunct_thread_func(void *arg) { defunct_tid = sys_gettid(); + sprintf(buf, "/proc/pid/task/%d", defunct_tid); + return arg; } @@ -73,18 +77,23 @@ static const struct testcase { const int sig; const int err; } testcases[] = { - { "Invalid tgid", &invalid_pid, &parent_tid, SIGUSR1, EINVAL }, - { "Invalid tid", &parent_tgid, &invalid_pid, SIGUSR1, EINVAL }, - { "Invalid signal", &parent_tgid, &parent_tid, -1, EINVAL }, +// { "Invalid tgid", &invalid_pid, &parent_tid, SIGUSR1, EINVAL }, +// { "Invalid tid", &parent_tgid, &invalid_pid, SIGUSR1, EINVAL }, +// { "Invalid signal", &parent_tgid, &parent_tid, -1, EINVAL }, { "Defunct tid", &parent_tgid, &defunct_tid, SIGUSR1, ESRCH }, - { "Defunct tgid", &defunct_tid, &child_tid, SIGUSR1, ESRCH }, - { "Valid tgkill call", &parent_tgid, &child_tid, SIGUSR1, 0 }, +// { "Defunct tgid", &defunct_tid, &child_tid, SIGUSR1, ESRCH }, +// { "Valid tgkill call", &parent_tgid, &child_tid, SIGUSR1, 0 }, }; static void run(unsigned int i) { const struct testcase *tc = &testcases[i]; + // debug code // + while (access(buf, F_OK) == 0) { + tst_res(TINFO, "Debug: %s still exist!", buf); + } + TEST(sys_tgkill(*tc->tgid, *tc->tid, tc->sig)); if (tc->err) { if (TST_RET < 0 && TST_ERR == tc->err) -- Regards, Li Wang <div dir="ltr"><div dir="ltr"><div class="gmail_default" style="font-size:small"><br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Sun, Jun 16, 2019 at 7:08 AM Jan Stancek <<a href="mailto:jstancek@redhat.com">jstancek@redhat.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><br> ----- Original Message -----<br> > +static void setup(void)<br> > +{<br> > + sigset_t sigusr1;<br> > + pthread_t defunct_thread;<br> > +<br> > + sigemptyset(&sigusr1);<br> > + sigaddset(&sigusr1, SIGUSR1);<br> > + pthread_sigmask(SIG_BLOCK, &sigusr1, NULL);<br> > +<br> > + parent_tgid = getpid();<br> > + parent_tid = sys_gettid();<br> > +<br> > + SAFE_PTHREAD_CREATE(&child_thread, NULL, child_thread_func, NULL);<br> > +<br> > + TST_CHECKPOINT_WAIT(0);<br> <br> I'm seeing reports of this test failing on s390x:<br> <br> st_test.c:1096: INFO: Timeout per run is 0h 05m 00s<br> tgkill03.c:92: PASS: Invalid tgid failed as expected: EINVAL<br> tgkill03.c:92: PASS: Invalid tid failed as expected: EINVAL<br> tgkill03.c:92: PASS: Invalid signal failed as expected: EINVAL<br> tgkill03.c:96: FAIL: Defunct tid should have failed with ESRCH: SUCCESS<br> tgkill03.c:92: PASS: Defunct tgid failed as expected: ESRCH<br> tgkill03.c:99: PASS: Valid tgkill call succeeded<br> <br> and I suspect this piece:<br> <br> > +<br> > + SAFE_PTHREAD_CREATE(&defunct_thread, NULL, defunct_thread_func, NULL);<br> > +<br> > + SAFE_PTHREAD_JOIN(defunct_thread, NULL);<br> > +}<br> <br> glibc pthread_join() waits for CLONE_CHILD_CLEARTID to clear tid,<br> and then resumes. Which kernel does at:<br> do_exit<br> exit_mm<br> mm_release<br> put_user(0, tsk->clear_child_tid);<br> <br> so there's still work to be done after that, and I suspect tid is still valid<br> while that happens.<br> <br> My first idea: wait until /proc/pid/task/<tid> disappears.<br></blockquote><div><br></div><div class="gmail_default" style="font-size:small">The anaysis is probably right, but this idea doesn't work for me. Seems /proc/pid/task/<tid> is not the key point to confirm that tid has been clear.</div><div class="gmail_default" style="font-size:small"><br></div><div class="gmail_default" style="font-size:small">I just have a try as below:</div><div class="gmail_default" style="font-size:small"><br></div><div class="gmail_default" style="font-size:small"><div class="gmail_default">===========<br class="gmail-Apple-interchange-newline"># for i in `seq 1000`; do echo "i = $i" && ./tgkill03 || break; done<br></div><div class="gmail_default">...</div>i = 96<br>tst_test.c:1112: INFO: Timeout per run is 0h 05m 00s<br>tgkill03.c:106: FAIL: Defunct tid should have failed with ESRCH: SUCCESS<br></div><div class="gmail_default" style="font-size:small"><br></div><div class="gmail_default" style="font-size:small">===========</div><div class="gmail_default" style="font-size:small">--- a/testcases/kernel/syscalls/tgkill/tgkill03.c<br>+++ b/testcases/kernel/syscalls/tgkill/tgkill03.c<br>@@ -5,6 +5,7 @@<br> * Test simple tgkill() error cases.<br> */<br> <br>+#include <stdio.h><br> #include <pthread.h><br> #include <pwd.h><br> #include <sys/types.h><br>@@ -19,6 +20,7 @@ static pid_t parent_tgid;<br> static pid_t parent_tid;<br> static pid_t child_tid;<br> static pid_t defunct_tid;<br>+char buf[1024];<br> <br> static const int invalid_pid = -1;<br> <br>@@ -35,6 +37,8 @@ static void *defunct_thread_func(void *arg)<br> {<br> defunct_tid = sys_gettid();<br> <br>+ sprintf(buf, "/proc/pid/task/%d", defunct_tid);<br>+<br> return arg;<br> }<br> <br>@@ -73,18 +77,23 @@ static const struct testcase {<br> const int sig;<br> const int err;<br> } testcases[] = {<br>- { "Invalid tgid", &invalid_pid, &parent_tid, SIGUSR1, EINVAL },<br>- { "Invalid tid", &parent_tgid, &invalid_pid, SIGUSR1, EINVAL },<br>- { "Invalid signal", &parent_tgid, &parent_tid, -1, EINVAL },<br>+// { "Invalid tgid", &invalid_pid, &parent_tid, SIGUSR1, EINVAL },<br>+// { "Invalid tid", &parent_tgid, &invalid_pid, SIGUSR1, EINVAL },<br>+// { "Invalid signal", &parent_tgid, &parent_tid, -1, EINVAL },<br> { "Defunct tid", &parent_tgid, &defunct_tid, SIGUSR1, ESRCH },<br>- { "Defunct tgid", &defunct_tid, &child_tid, SIGUSR1, ESRCH },<br>- { "Valid tgkill call", &parent_tgid, &child_tid, SIGUSR1, 0 },<br>+// { "Defunct tgid", &defunct_tid, &child_tid, SIGUSR1, ESRCH },<br>+// { "Valid tgkill call", &parent_tgid, &child_tid, SIGUSR1, 0 },<br> };<br> <br> static void run(unsigned int i)<br> {<br> const struct testcase *tc = &testcases[i];<br> <br>+ // debug code //<br>+ while (access(buf, F_OK) == 0) {<br>+ tst_res(TINFO, "Debug: %s still exist!", buf);<br>+ }<br>+<br> TEST(sys_tgkill(*tc->tgid, *tc->tid, tc->sig));<br> if (tc->err) {<br> if (TST_RET < 0 && TST_ERR == tc->err)<br></div><div class="gmail_default" style="font-size:small"><br></div></div><div><br></div>-- <br><div dir="ltr" class="gmail_signature"><div dir="ltr"><div>Regards,<br></div><div>Li Wang<br></div></div></div></div>
----- Original Message ----- > On Sun, Jun 16, 2019 at 7:08 AM Jan Stancek <jstancek@redhat.com> wrote: > > > > > ----- Original Message ----- > > > +static void setup(void) > > > +{ > > > + sigset_t sigusr1; > > > + pthread_t defunct_thread; > > > + > > > + sigemptyset(&sigusr1); > > > + sigaddset(&sigusr1, SIGUSR1); > > > + pthread_sigmask(SIG_BLOCK, &sigusr1, NULL); > > > + > > > + parent_tgid = getpid(); > > > + parent_tid = sys_gettid(); > > > + > > > + SAFE_PTHREAD_CREATE(&child_thread, NULL, child_thread_func, NULL); > > > + > > > + TST_CHECKPOINT_WAIT(0); > > > > I'm seeing reports of this test failing on s390x: > > > > st_test.c:1096: INFO: Timeout per run is 0h 05m 00s > > tgkill03.c:92: PASS: Invalid tgid failed as expected: EINVAL > > tgkill03.c:92: PASS: Invalid tid failed as expected: EINVAL > > tgkill03.c:92: PASS: Invalid signal failed as expected: EINVAL > > tgkill03.c:96: FAIL: Defunct tid should have failed with ESRCH: SUCCESS > > tgkill03.c:92: PASS: Defunct tgid failed as expected: ESRCH > > tgkill03.c:99: PASS: Valid tgkill call succeeded > > > > and I suspect this piece: > > > > > + > > > + SAFE_PTHREAD_CREATE(&defunct_thread, NULL, defunct_thread_func, > > NULL); > > > + > > > + SAFE_PTHREAD_JOIN(defunct_thread, NULL); > > > +} > > > > glibc pthread_join() waits for CLONE_CHILD_CLEARTID to clear tid, > > and then resumes. Which kernel does at: > > do_exit > > exit_mm > > mm_release > > put_user(0, tsk->clear_child_tid); > > > > so there's still work to be done after that, and I suspect tid is still > > valid > > while that happens. > > > > My first idea: wait until /proc/pid/task/<tid> disappears. > > > > The anaysis is probably right, but this idea doesn't work for me. Seems > /proc/pid/task/<tid> is not the key point to confirm that tid has been > clear. > > I just have a try as below: > > =========== > # for i in `seq 1000`; do echo "i = $i" && ./tgkill03 || break; done > ... > i = 96 > tst_test.c:1112: INFO: Timeout per run is 0h 05m 00s > tgkill03.c:106: FAIL: Defunct tid should have failed with ESRCH: SUCCESS > > =========== > --- a/testcases/kernel/syscalls/tgkill/tgkill03.c > +++ b/testcases/kernel/syscalls/tgkill/tgkill03.c > @@ -5,6 +5,7 @@ > * Test simple tgkill() error cases. > */ > > +#include <stdio.h> > #include <pthread.h> > #include <pwd.h> > #include <sys/types.h> > @@ -19,6 +20,7 @@ static pid_t parent_tgid; > static pid_t parent_tid; > static pid_t child_tid; > static pid_t defunct_tid; > +char buf[1024]; > > static const int invalid_pid = -1; > > @@ -35,6 +37,8 @@ static void *defunct_thread_func(void *arg) > { > defunct_tid = sys_gettid(); > > + sprintf(buf, "/proc/pid/task/%d", defunct_tid); How about? sprintf(buf, "/proc/%d/task/%d", getpid(), defunct_tid);
On Sun, Jun 16, 2019 at 3:04 PM Jan Stancek <jstancek@redhat.com> wrote: > > > ----- Original Message ----- > > On Sun, Jun 16, 2019 at 7:08 AM Jan Stancek <jstancek@redhat.com> wrote: > > > > > > > > ----- Original Message ----- > > > > +static void setup(void) > > > > +{ > > > > + sigset_t sigusr1; > > > > + pthread_t defunct_thread; > > > > + > > > > + sigemptyset(&sigusr1); > > > > + sigaddset(&sigusr1, SIGUSR1); > > > > + pthread_sigmask(SIG_BLOCK, &sigusr1, NULL); > > > > + > > > > + parent_tgid = getpid(); > > > > + parent_tid = sys_gettid(); > > > > + > > > > + SAFE_PTHREAD_CREATE(&child_thread, NULL, child_thread_func, > NULL); > > > > + > > > > + TST_CHECKPOINT_WAIT(0); > > > > > > I'm seeing reports of this test failing on s390x: > > > > > > st_test.c:1096: INFO: Timeout per run is 0h 05m 00s > > > tgkill03.c:92: PASS: Invalid tgid failed as expected: EINVAL > > > tgkill03.c:92: PASS: Invalid tid failed as expected: EINVAL > > > tgkill03.c:92: PASS: Invalid signal failed as expected: EINVAL > > > tgkill03.c:96: FAIL: Defunct tid should have failed with ESRCH: SUCCESS > > > tgkill03.c:92: PASS: Defunct tgid failed as expected: ESRCH > > > tgkill03.c:99: PASS: Valid tgkill call succeeded > > > > > > and I suspect this piece: > > > > > > > + > > > > + SAFE_PTHREAD_CREATE(&defunct_thread, NULL, defunct_thread_func, > > > NULL); > > > > + > > > > + SAFE_PTHREAD_JOIN(defunct_thread, NULL); > > > > +} > > > > > > glibc pthread_join() waits for CLONE_CHILD_CLEARTID to clear tid, > > > and then resumes. Which kernel does at: > > > do_exit > > > exit_mm > > > mm_release > > > put_user(0, tsk->clear_child_tid); > > > > > > so there's still work to be done after that, and I suspect tid is still > > > valid > > > while that happens. > > > > > > My first idea: wait until /proc/pid/task/<tid> disappears. > > > > > > > The anaysis is probably right, but this idea doesn't work for me. Seems > > /proc/pid/task/<tid> is not the key point to confirm that tid has been > > clear. > > > > I just have a try as below: > > > > =========== > > # for i in `seq 1000`; do echo "i = $i" && ./tgkill03 || break; done > > ... > > i = 96 > > tst_test.c:1112: INFO: Timeout per run is 0h 05m 00s > > tgkill03.c:106: FAIL: Defunct tid should have failed with ESRCH: SUCCESS > > > > =========== > > --- a/testcases/kernel/syscalls/tgkill/tgkill03.c > > +++ b/testcases/kernel/syscalls/tgkill/tgkill03.c > > @@ -5,6 +5,7 @@ > > * Test simple tgkill() error cases. > > */ > > > > +#include <stdio.h> > > #include <pthread.h> > > #include <pwd.h> > > #include <sys/types.h> > > @@ -19,6 +20,7 @@ static pid_t parent_tgid; > > static pid_t parent_tid; > > static pid_t child_tid; > > static pid_t defunct_tid; > > +char buf[1024]; > > > > static const int invalid_pid = -1; > > > > @@ -35,6 +37,8 @@ static void *defunct_thread_func(void *arg) > > { > > defunct_tid = sys_gettid(); > > > > + sprintf(buf, "/proc/pid/task/%d", defunct_tid); > > How about? > sprintf(buf, "/proc/%d/task/%d", getpid(), defunct_tid); > > Ah, I was stupid to lost the getpid :-). This look prettry good. The test fall into while loop when defunct_tid is still exit, and get the expected result once /proc/pid/task/<tid> disappears. # for i in `seq 1000`; do echo "i = $i" && ./tgkill03 || break; done ... i = 997 tst_test.c:1112: INFO: Timeout per run is 0h 05m 00s tgkill03.c:95: INFO: Debug: /proc/5164/task/5166 still exist! tgkill03.c:95: INFO: Debug: /proc/5164/task/5166 still exist! tgkill03.c:95: INFO: Debug: /proc/5164/task/5166 still exist! tgkill03.c:95: INFO: Debug: /proc/5164/task/5166 still exist! tgkill03.c:95: INFO: Debug: /proc/5164/task/5166 still exist! tgkill03.c:95: INFO: Debug: /proc/5164/task/5166 still exist! tgkill03.c:95: INFO: Debug: /proc/5164/task/5166 still exist! tgkill03.c:95: INFO: Debug: /proc/5164/task/5166 still exist! tgkill03.c:95: INFO: Debug: /proc/5164/task/5166 still exist! tgkill03.c:95: INFO: Debug: /proc/5164/task/5166 still exist! tgkill03.c:95: INFO: Debug: /proc/5164/task/5166 still exist! tgkill03.c:95: INFO: Debug: /proc/5164/task/5166 still exist! tgkill03.c:95: INFO: Debug: /proc/5164/task/5166 still exist! tgkill03.c:95: INFO: Debug: /proc/5164/task/5166 still exist! tgkill03.c:95: INFO: Debug: /proc/5164/task/5166 still exist! tgkill03.c:95: INFO: Debug: /proc/5164/task/5166 still exist! tgkill03.c:95: INFO: Debug: /proc/5164/task/5166 still exist! tgkill03.c:95: INFO: Debug: /proc/5164/task/5166 still exist! tgkill03.c:95: INFO: Debug: /proc/5164/task/5166 still exist! tgkill03.c:95: INFO: Debug: /proc/5164/task/5166 still exist! tgkill03.c:95: INFO: Debug: /proc/5164/task/5166 still exist! tgkill03.c:95: INFO: Debug: /proc/5164/task/5166 still exist! tgkill03.c:95: INFO: Debug: /proc/5164/task/5166 still exist! tgkill03.c:95: INFO: Debug: /proc/5164/task/5166 still exist! tgkill03.c:95: INFO: Debug: /proc/5164/task/5166 still exist! tgkill03.c:95: INFO: Debug: /proc/5164/task/5166 still exist! tgkill03.c:95: INFO: Debug: /proc/5164/task/5166 still exist! tgkill03.c:95: INFO: Debug: /proc/5164/task/5166 still exist! tgkill03.c:95: INFO: Debug: /proc/5164/task/5166 still exist! tgkill03.c:95: INFO: Debug: /proc/5164/task/5166 still exist! tgkill03.c:95: INFO: Debug: /proc/5164/task/5166 still exist! tgkill03.c:95: INFO: Debug: /proc/5164/task/5166 still exist! tgkill03.c:95: INFO: Debug: /proc/5164/task/5166 still exist! tgkill03.c:95: INFO: Debug: /proc/5164/task/5166 still exist! tgkill03.c:95: INFO: Debug: /proc/5164/task/5166 still exist! tgkill03.c:102: PASS: Defunct tgid failed as expected: ESRCH Summary: passed 1 failed 0 skipped 0 warnings 0 ... i = 1000 tst_test.c:1112: INFO: Timeout per run is 0h 05m 00s tgkill03.c:102: PASS: Defunct tgid failed as expected: ESRCH Summary: passed 1 failed 0 skipped 0 warnings 0 -- Regards, Li Wang <div dir="ltr"><div dir="ltr"><div class="gmail_default" style="font-size:small"><br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Sun, Jun 16, 2019 at 3:04 PM Jan Stancek <<a href="mailto:jstancek@redhat.com">jstancek@redhat.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><br> <br> ----- Original Message -----<br> > On Sun, Jun 16, 2019 at 7:08 AM Jan Stancek <<a href="mailto:jstancek@redhat.com" target="_blank">jstancek@redhat.com</a>> wrote:<br> > <br> > ><br> > > ----- Original Message -----<br> > > > +static void setup(void)<br> > > > +{<br> > > > + sigset_t sigusr1;<br> > > > + pthread_t defunct_thread;<br> > > > +<br> > > > + sigemptyset(&sigusr1);<br> > > > + sigaddset(&sigusr1, SIGUSR1);<br> > > > + pthread_sigmask(SIG_BLOCK, &sigusr1, NULL);<br> > > > +<br> > > > + parent_tgid = getpid();<br> > > > + parent_tid = sys_gettid();<br> > > > +<br> > > > + SAFE_PTHREAD_CREATE(&child_thread, NULL, child_thread_func, NULL);<br> > > > +<br> > > > + TST_CHECKPOINT_WAIT(0);<br> > ><br> > > I'm seeing reports of this test failing on s390x:<br> > ><br> > > st_test.c:1096: INFO: Timeout per run is 0h 05m 00s<br> > > tgkill03.c:92: PASS: Invalid tgid failed as expected: EINVAL<br> > > tgkill03.c:92: PASS: Invalid tid failed as expected: EINVAL<br> > > tgkill03.c:92: PASS: Invalid signal failed as expected: EINVAL<br> > > tgkill03.c:96: FAIL: Defunct tid should have failed with ESRCH: SUCCESS<br> > > tgkill03.c:92: PASS: Defunct tgid failed as expected: ESRCH<br> > > tgkill03.c:99: PASS: Valid tgkill call succeeded<br> > ><br> > > and I suspect this piece:<br> > ><br> > > > +<br> > > > + SAFE_PTHREAD_CREATE(&defunct_thread, NULL, defunct_thread_func,<br> > > NULL);<br> > > > +<br> > > > + SAFE_PTHREAD_JOIN(defunct_thread, NULL);<br> > > > +}<br> > ><br> > > glibc pthread_join() waits for CLONE_CHILD_CLEARTID to clear tid,<br> > > and then resumes. Which kernel does at:<br> > > do_exit<br> > > exit_mm<br> > > mm_release<br> > > put_user(0, tsk->clear_child_tid);<br> > ><br> > > so there's still work to be done after that, and I suspect tid is still<br> > > valid<br> > > while that happens.<br> > ><br> > > My first idea: wait until /proc/pid/task/<tid> disappears.<br> > ><br> > <br> > The anaysis is probably right, but this idea doesn't work for me. Seems<br> > /proc/pid/task/<tid> is not the key point to confirm that tid has been<br> > clear.<br> > <br> > I just have a try as below:<br> > <br> > ===========<br> > # for i in `seq 1000`; do echo "i = $i" && ./tgkill03 || break; done<br> > ...<br> > i = 96<br> > tst_test.c:1112: INFO: Timeout per run is 0h 05m 00s<br> > tgkill03.c:106: FAIL: Defunct tid should have failed with ESRCH: SUCCESS<br> > <br> > ===========<br> > --- a/testcases/kernel/syscalls/tgkill/tgkill03.c<br> > +++ b/testcases/kernel/syscalls/tgkill/tgkill03.c<br> > @@ -5,6 +5,7 @@<br> > * Test simple tgkill() error cases.<br> > */<br> > <br> > +#include <stdio.h><br> > #include <pthread.h><br> > #include <pwd.h><br> > #include <sys/types.h><br> > @@ -19,6 +20,7 @@ static pid_t parent_tgid;<br> > static pid_t parent_tid;<br> > static pid_t child_tid;<br> > static pid_t defunct_tid;<br> > +char buf[1024];<br> > <br> > static const int invalid_pid = -1;<br> > <br> > @@ -35,6 +37,8 @@ static void *defunct_thread_func(void *arg)<br> > {<br> > defunct_tid = sys_gettid();<br> > <br> > + sprintf(buf, "/proc/pid/task/%d", defunct_tid);<br> <br> How about?<br> sprintf(buf, "/proc/%d/task/%d", getpid(), defunct_tid);<br> <br></blockquote><div><br></div><div class="gmail_default" style="font-size:small">Ah, I was stupid to lost the getpid :-).</div><div class="gmail_default" style="font-size:small"><br></div><div class="gmail_default" style="font-size:small">This look prettry good. The test fall into while loop when defunct_tid is still exit, and get the expected result once /proc/pid/task/<tid> disappears.</div><div class="gmail_default" style="font-size:small"><br></div><div class="gmail_default" style="font-size:small"># for i in `seq 1000`; do echo "i = $i" && ./tgkill03 || break; done<br></div><div class="gmail_default" style="font-size:small">...</div><div class="gmail_default" style="font-size:small">i = 997<br>tst_test.c:1112: INFO: Timeout per run is 0h 05m 00s<br></div><span class="gmail_default" style="font-size:small"></span>tgkill03.c:95: INFO: Debug: /proc/5164/task/5166 still exist!<br>tgkill03.c:95: INFO: Debug: /proc/5164/task/5166 still exist!<br>tgkill03.c:95: INFO: Debug: /proc/5164/task/5166 still exist!<br>tgkill03.c:95: INFO: Debug: /proc/5164/task/5166 still exist!<br>tgkill03.c:95: INFO: Debug: /proc/5164/task/5166 still exist!<br>tgkill03.c:95: INFO: Debug: /proc/5164/task/5166 still exist!<br>tgkill03.c:95: INFO: Debug: /proc/5164/task/5166 still exist!<br>tgkill03.c:95: INFO: Debug: /proc/5164/task/5166 still exist!<br>tgkill03.c:95: INFO: Debug: /proc/5164/task/5166 still exist!<br>tgkill03.c:95: INFO: Debug: /proc/5164/task/5166 still exist!<br>tgkill03.c:95: INFO: Debug: /proc/5164/task/5166 still exist!<br>tgkill03.c:95: INFO: Debug: /proc/5164/task/5166 still exist!<br>tgkill03.c:95: INFO: Debug: /proc/5164/task/5166 still exist!<br>tgkill03.c:95: INFO: Debug: /proc/5164/task/5166 still exist!<br>tgkill03.c:95: INFO: Debug: /proc/5164/task/5166 still exist!<br>tgkill03.c:95: INFO: Debug: /proc/5164/task/5166 still exist!<br>tgkill03.c:95: INFO: Debug: /proc/5164/task/5166 still exist!<br>tgkill03.c:95: INFO: Debug: /proc/5164/task/5166 still exist!<br>tgkill03.c:95: INFO: Debug: /proc/5164/task/5166 still exist!<br>tgkill03.c:95: INFO: Debug: /proc/5164/task/5166 still exist!<br>tgkill03.c:95: INFO: Debug: /proc/5164/task/5166 still exist!<br>tgkill03.c:95: INFO: Debug: /proc/5164/task/5166 still exist!<br>tgkill03.c:95: INFO: Debug: /proc/5164/task/5166 still exist!<br>tgkill03.c:95: INFO: Debug: /proc/5164/task/5166 still exist!<br>tgkill03.c:95: INFO: Debug: /proc/5164/task/5166 still exist!<br>tgkill03.c:95: INFO: Debug: /proc/5164/task/5166 still exist!<br>tgkill03.c:95: INFO: Debug: /proc/5164/task/5166 still exist!<br>tgkill03.c:95: INFO: Debug: /proc/5164/task/5166 still exist!<br>tgkill03.c:95: INFO: Debug: /proc/5164/task/5166 still exist!<br>tgkill03.c:95: INFO: Debug: /proc/5164/task/5166 still exist!<br>tgkill03.c:95: INFO: Debug: /proc/5164/task/5166 still exist!<br>tgkill03.c:95: INFO: Debug: /proc/5164/task/5166 still exist!<br>tgkill03.c:95: INFO: Debug: /proc/5164/task/5166 still exist!<br>tgkill03.c:95: INFO: Debug: /proc/5164/task/5166 still exist!<br>tgkill03.c:95: INFO: Debug: /proc/5164/task/5166 still exist!<br>tgkill03.c:102: PASS: Defunct tgid failed as expected: ESRCH<br><br>Summary:<br>passed 1<br>failed 0<br>skipped 0<br>warnings 0</div><div class="gmail_quote"><div class="gmail_default" style="font-size:small"></div><div class="gmail_default" style="font-size:small">...</div><div class="gmail_default" style="font-size:small">i = 1000</div>tst_test.c:1112: INFO: Timeout per run is 0h 05m 00s<br>tgkill03.c:102: PASS: Defunct tgid failed as expected: ESRCH<br><br>Summary:<br>passed 1<br>failed 0<br>skipped 0<br>warnings 0</div><div><br></div>-- <br><div dir="ltr" class="gmail_signature"><div dir="ltr"><div>Regards,<br></div><div>Li Wang<br></div></div></div></div>
diff --git a/runtest/syscalls b/runtest/syscalls index 7af9136..b090408 100644 --- a/runtest/syscalls +++ b/runtest/syscalls @@ -1402,6 +1402,7 @@ syslog12 syslog12 tgkill01 tgkill01 tgkill02 tgkill02 +tgkill03 tgkill03 time01 time01 time02 time02 diff --git a/testcases/kernel/syscalls/tgkill/.gitignore b/testcases/kernel/syscalls/tgkill/.gitignore index 42be2bb..a6d2299 100644 --- a/testcases/kernel/syscalls/tgkill/.gitignore +++ b/testcases/kernel/syscalls/tgkill/.gitignore @@ -1,2 +1,3 @@ tgkill01 tgkill02 +tgkill03 diff --git a/testcases/kernel/syscalls/tgkill/tgkill03.c b/testcases/kernel/syscalls/tgkill/tgkill03.c new file mode 100644 index 0000000..b78e9d9 --- /dev/null +++ b/testcases/kernel/syscalls/tgkill/tgkill03.c @@ -0,0 +1,110 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2018 Google, Inc. + * + * Test simple tgkill() error cases. + */ + +#include <pthread.h> +#include <pwd.h> +#include <sys/types.h> + +#include "tst_safe_pthread.h" +#include "tst_test.h" +#include "tgkill.h" + +static pthread_t child_thread; + +static pid_t parent_tgid; +static pid_t parent_tid; +static pid_t child_tid; +static pid_t defunct_tid; + +static const int invalid_pid = -1; + +static void *child_thread_func(void *arg) +{ + child_tid = sys_gettid(); + + TST_CHECKPOINT_WAKE_AND_WAIT(0); + + return arg; +} + +static void *defunct_thread_func(void *arg) +{ + defunct_tid = sys_gettid(); + + return arg; +} + +static void setup(void) +{ + sigset_t sigusr1; + pthread_t defunct_thread; + + sigemptyset(&sigusr1); + sigaddset(&sigusr1, SIGUSR1); + pthread_sigmask(SIG_BLOCK, &sigusr1, NULL); + + parent_tgid = getpid(); + parent_tid = sys_gettid(); + + SAFE_PTHREAD_CREATE(&child_thread, NULL, child_thread_func, NULL); + + TST_CHECKPOINT_WAIT(0); + + SAFE_PTHREAD_CREATE(&defunct_thread, NULL, defunct_thread_func, NULL); + + SAFE_PTHREAD_JOIN(defunct_thread, NULL); +} + +static void cleanup(void) +{ + TST_CHECKPOINT_WAKE(0); + + SAFE_PTHREAD_JOIN(child_thread, NULL); +} + +static const struct testcase { + const char *desc; + const int *tgid; + const int *tid; + const int sig; + const int err; +} testcases[] = { + { "Invalid tgid", &invalid_pid, &parent_tid, SIGUSR1, EINVAL }, + { "Invalid tid", &parent_tgid, &invalid_pid, SIGUSR1, EINVAL }, + { "Invalid signal", &parent_tgid, &parent_tid, -1, EINVAL }, + { "Defunct thread ID", &parent_tgid, &defunct_tid, SIGUSR1, ESRCH }, + { "Valid tgkill call", &parent_tgid, &child_tid, SIGUSR1, 0 }, +}; + +static void run(unsigned int i) +{ + const struct testcase *tc = &testcases[i]; + + TEST(sys_tgkill(*tc->tgid, *tc->tid, tc->sig)); + if (tc->err) { + if (TST_RET < 0 && TST_ERR == tc->err) + tst_res(TPASS | TTERRNO, "%s failed as expected", + tc->desc); + else + tst_res(TFAIL | TTERRNO, + "%s should have failed with %s", tc->desc, + tst_strerrno(tc->err)); + } else { + if (TST_RET == 0) + tst_res(TPASS, "%s succeeded", tc->desc); + else + tst_res(TFAIL | TTERRNO, "%s failed", tc->desc); + } +} + +static struct tst_test test = { + .tcnt = ARRAY_SIZE(testcases), + .needs_checkpoints = 1, + .setup = setup, + .cleanup = cleanup, + .test = run, +};