From: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
To: Florian Weimer <fweimer@redhat.com>
Cc: libc-alpha <libc-alpha@sourceware.org>,
Joseph Myers <joseph@codesourcery.com>
Subject: Re: [PATCH glibc 3/3] rseq registration tests (v10)
Date: Tue, 26 May 2020 10:43:15 -0400 (EDT) [thread overview]
Message-ID: <1647263261.34186.1590504195448.JavaMail.zimbra@efficios.com> (raw)
In-Reply-To: <87h7w2rhg2.fsf@oldenburg2.str.redhat.com>
----- On May 26, 2020, at 8:47 AM, Florian Weimer fweimer@redhat.com wrote:
> * Mathieu Desnoyers:
>
>>> The present code does not wait until all threads have entered their
>>> cancellation region, so I'm not sure if the test object is actually met
>>> here.
>>
>> We're only cancelling the first thread in the test, which is the intent.
>> In terms of barrier, it's a barrier involving only 2 threads.
>
> Huh. I need to look at the version with the real barrier.
Useful bits:
static void
cancel_routine (void *arg)
{
if (!rseq_thread_registered ())
{
printf ("error: rseq not registered in cancel routine\n");
support_record_failure ();
}
}
static pthread_barrier_t cancel_thread_barrier;
static pthread_cond_t cancel_thread_cond = PTHREAD_COND_INITIALIZER;
static pthread_mutex_t cancel_thread_mutex = PTHREAD_MUTEX_INITIALIZER;
static void
test_cancel_thread (void)
{
pthread_cleanup_push (cancel_routine, NULL);
(void) xpthread_barrier_wait (&cancel_thread_barrier);
/* Wait forever until cancellation. */
xpthread_cond_wait (&cancel_thread_cond, &cancel_thread_mutex);
pthread_cleanup_pop (0);
}
static void *
thread_function (void * arg)
{
int i = (int) (intptr_t) arg;
xraise (SIGUSR1);
if (i == 0)
test_cancel_thread ();
TEST_COMPARE (pthread_setspecific (rseq_test_key, (void *) 1l), 0);
return rseq_thread_registered () ? NULL : (void *) 1l;
}
static int
do_rseq_threads_test (int nr_threads)
{
pthread_t th[nr_threads];
int i;
int result = 0;
xpthread_barrier_init (&cancel_thread_barrier, NULL, 2);
for (i = 0; i < nr_threads; ++i)
th[i] = xpthread_create (NULL, thread_function,
(void *) (intptr_t) i);
(void) xpthread_barrier_wait (&cancel_thread_barrier);
xpthread_cancel (th[0]);
for (i = 0; i < nr_threads; ++i)
{
void *v;
v = xpthread_join (th[i]);
if (i != 0 && v != NULL)
{
printf ("error: join %d successful, but child failed\n", i);
result = 1;
}
else if (i == 0 && v == NULL)
{
printf ("error: join %d successful, child did not fail as expected\n", i);
result = 1;
}
}
xpthread_barrier_destroy (&cancel_thread_barrier);
return result;
}
>
>>>> +static int
>>>> +rseq_available (void)
>>>> +{
>>>> + int rc;
>>>> +
>>>> + rc = sys_rseq (NULL, 0, 0, 0);
>>>> + if (rc != -1)
>>>> + FAIL_EXIT1 ("Unexpected rseq return value %d", rc);
>>>> + switch (errno)
>>>> + {
>>>> + case ENOSYS:
>>>> + return 0;
>>>> + case EINVAL:
>>>> + return 1;
>>>> + default:
>>>> + FAIL_EXIT1 ("Unexpected rseq error %s", strerror (errno));
>>>> + }
>>>> +}
>>>
>>> Maybe add a comment to explain what EINVAL means in this context?
>>
>> For instance:
>>
>> /* rseq is implemented, but detected an invalid parameter. */
>
> Ah, so 0 is an invalid operation?
So the @flags parameter is 0, which is fine.
It's the @rseq_len parameter being 0 (which differs from sizeof(struct rseq))
which returns -EINVAL. I will clarify this in the comment:
/* rseq is implemented, but detected an invalid rseq_len parameter. */
>
>>>> + retpid = TEMP_FAILURE_RETRY (waitpid (pid, &status, 0));
>>>> + if (retpid != pid)
>>>> + {
>>>> + FAIL_EXIT1 ("waitpid returned %ld, expected %ld",
>>>> + (long int) retpid, (long int) pid);
>>>> + }
>>>
>>> Hmm. Is the TEMP_FAILURE_RETRY really needed? Our xwaitpid does not
>>> have this.
>>
>> Then how does it deal with a signal interrupting the system call performing
>> the waitpid (EINTR) ? I do not see WNOHANG being used.
>
> It obscures spurious signals. In most test cases, if an unexpected
> signal is delivered, something is quite wrong indeed. This is why we
> don't generally hide EINTR errors.
So it means you may have trouble using tools like strace and gdb on those
tests ? AFAIU those are heavy users of SIGSTOP and SIGCONT. Similarly for
profilers, those usually rely on a timer-driven signal.
>
>>>> +/* Test C++ destructor called at thread and process exit. */
>>>> +void
>>>> +__call_tls_dtors (void)
>>>> +{
>>>> + /* Cannot use deferred failure reporting after main () returns. */
>>>> + if (!rseq_thread_registered ())
>>>> + FAIL_EXIT1 ("rseq not registered in C++ thread/process exit destructor");
>>>> +}
>>>
>>> Uhm, what is this supposed to accomplish, under the __call_tls_dtors
>>> name in particular? I don't think this gets ever called.
>>>
>>> It may make sense to have a separate, smaller C++ test to cover this
>>> (perhaps as a separate patch).
>>
>> Hrm, the intent was to implement __call_tls_dtors locally so it would
>> be invoked by libc on thread/process exit, but looking deeper into
>> stdlib/cxa_thread_atexit_impl.c I suspect the hidden _call_tls_dtors
>> defined there will be used.
>
> Right, it's not an interposable symbol.
>
>> Indeed, a separate C++ test for this would be better. Could be done in a
>> follow up patch later perhaps ?
>
> Yes, let's remove this and add a real C++ test later.
OK
>
>>> C++ test could exercise the thread exit path via thread_local, without
>>> linking against libpthread.
>>
>> Should we keep this for a future patch ?
>
> Yes, please.
OK, thanks!
Mathieu
>
> Thanks,
> Florian
--
Mathieu Desnoyers
EfficiOS Inc.
http://www.efficios.com
next prev parent reply other threads:[~2020-05-26 14:43 UTC|newest]
Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-05-01 2:14 [PATCH glibc 0/3] Restartable Sequences enablement Mathieu Desnoyers
2020-05-01 2:14 ` [PATCH glibc 1/3] glibc: Perform rseq registration at C startup and thread creation (v19) Mathieu Desnoyers
2020-05-20 11:40 ` Florian Weimer
2020-05-25 14:51 ` Mathieu Desnoyers
2020-05-25 15:20 ` Florian Weimer
2020-05-25 17:36 ` Mathieu Desnoyers
2020-05-26 12:41 ` Florian Weimer
2020-05-26 14:32 ` Mathieu Desnoyers
2020-05-26 14:38 ` Florian Weimer
2020-05-26 14:53 ` Mathieu Desnoyers
2020-05-26 14:57 ` Florian Weimer
2020-05-26 15:22 ` Mathieu Desnoyers
2020-05-01 2:14 ` [PATCH glibc 2/3] glibc: sched_getcpu(): use rseq cpu_id TLS on Linux (v7) Mathieu Desnoyers
2020-05-20 10:14 ` Florian Weimer
2020-05-01 2:14 ` [PATCH glibc 3/3] rseq registration tests (v10) Mathieu Desnoyers
2020-05-20 10:52 ` Florian Weimer
2020-05-25 17:07 ` Mathieu Desnoyers
2020-05-26 12:47 ` Florian Weimer
2020-05-26 14:43 ` Mathieu Desnoyers [this message]
2020-05-27 15:05 ` Mathieu Desnoyers
2020-05-27 15:12 ` Florian Weimer
2020-05-27 15:17 ` Mathieu Desnoyers
2020-05-27 15:21 ` Florian Weimer
2020-05-27 15:30 ` Mathieu Desnoyers
2020-05-20 11:44 ` [PATCH glibc 0/3] Restartable Sequences enablement Florian Weimer
2020-05-25 13:52 ` Mathieu Desnoyers
2020-05-25 14:28 ` Florian Weimer
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1647263261.34186.1590504195448.JavaMail.zimbra@efficios.com \
--to=mathieu.desnoyers@efficios.com \
--cc=fweimer@redhat.com \
--cc=joseph@codesourcery.com \
--cc=libc-alpha@sourceware.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).