[FFmpeg-devel] [PATCH] compat/w32pthreads: change pthread_t into pointer to malloced struct

Martin Storsjö martin at martin.st
Thu Dec 12 21:24:02 EET 2024


On Thu, 12 Dec 2024, Anton Khirnov wrote:

> Quoting Martin Storsjö (2024-12-12 18:40:27)
>> On Thu, 12 Dec 2024, Anton Khirnov wrote:
>> 
>> > pthread_t is currently defined as a struct, which gets placed into
>> > caller's memory and filled by pthread_create() (which accepts a
>> > pthread_t*).
>> >
>> > The problem with this approach is that pthread_join() accepts pthread_t
>> > itself rather than a pointer to it, so it gets a _copy_ of this
>> > structure. This causes non-deterministic failures of pthread_join() to
>> > produce the correct return value - depending on whether the thread
>> > already finished before pthread_join() is called (and thus the copy
>> > contains the correct value), or not (then it contains 0).
>> >
>> > Change the definition of pthread_t into a pointer to a struct, that gets
>> > malloced by pthread_create() and freed by pthread_join().
>> >
>> > Fixes random failures of fate-ffmpeg-error-rate-fail on Windows.
>> > ---
>> > compat/w32pthreads.h | 39 +++++++++++++++++++++++++++------------
>> > 1 file changed, 27 insertions(+), 12 deletions(-)
>> 
>> As you've pinpointed the commit that made this issue appear much more 
>> frequently, it'd be nice to include that info.
>
> Sure.
>
>> > diff --git a/compat/w32pthreads.h b/compat/w32pthreads.h
>> > index 2ff9735227..fd6428e29f 100644
>> > --- a/compat/w32pthreads.h
>> > +++ b/compat/w32pthreads.h
>> > @@ -50,7 +50,7 @@ typedef struct pthread_t {
>> >     void *(*func)(void* arg);
>> >     void *arg;
>> >     void *ret;
>> > -} pthread_t;
>> > +} *pthread_t;
>> >
>> > /* use light weight mutex/condition variable API for Windows Vista and later */
>> > typedef SRWLOCK pthread_mutex_t;
>> > @@ -74,7 +74,7 @@ typedef CONDITION_VARIABLE pthread_cond_t;
>> > static av_unused THREADFUNC_RETTYPE
>> > __stdcall attribute_align_arg win32thread_worker(void *arg)
>> > {
>> > -    pthread_t *h = (pthread_t*)arg;
>> > +    pthread_t h = (pthread_t)arg;
>> >     h->ret = h->func(h->arg);
>> >     return 0;
>> > }
>> > @@ -82,21 +82,35 @@ __stdcall attribute_align_arg win32thread_worker(void *arg)
>> > static av_unused int pthread_create(pthread_t *thread, const void *unused_attr,
>> >                                     void *(*start_routine)(void*), void *arg)
>> > {
>> > -    thread->func   = start_routine;
>> > -    thread->arg    = arg;
>> > +    pthread_t ret;
>> > +
>> > +    ret = av_mallocz(sizeof(*ret));
>> > +    if (!ret)
>> > +        return EAGAIN;
>> 
>> ENOMEM?
>
> POSIX specifies EAGAIN for "Insufficient resources to create another
> thread.", so...

That's weird - but fair enough then.

It could btw be useful trivia to link to 
https://code.videolan.org/videolan/x264/-/commit/23829dd2b2c909855481f46cc884b3c25d92c2d7 
as well, and say that this commit fixes the same issue, but we preferred 
to fix it this way, as this version doesn't break if the pthread_t is 
moved/copied.

// Martin


More information about the ffmpeg-devel mailing list