On 13/07/2018 20:42, Stefan Hajnoczi wrote:
> +#ifndef _WIN32
> +static void stop_writeout_thread(void)
> +{
> +    g_mutex_lock(&trace_lock);
> +    trace_writeout_running = false;
> +    g_cond_signal(&trace_available_cond);
> +    g_mutex_unlock(&trace_lock);
> +
> +    g_thread_join(trace_writeout_thread);
> +    trace_writeout_thread = NULL;
> +}

After stop_writeout_thread returns, another could start a write to the
shared data structure---and the write would never finish, because the
thread disappears after fork(2) returns.  This would leave the mutex
locked, causing a deadlock soon after the fork.  So you need to lock
trace_lock again here, and unlock it in restart_writeout_thread.

Apart from this, it looks good!

Thanks,

Paolo

> +static void restart_writeout_thread(void)
> +{
> +    trace_writeout_running = true;
> +    trace_writeout_thread = trace_thread_create(writeout_thread);
> +    if (!trace_writeout_thread) {
> +        warn_report("unable to initialize simple trace backend");
> +    }
> +}
> +#endif /* !_WIN32 */
> +
>  bool st_init(void)
>  {
> -    GThread *thread;
> -
>      trace_pid = getpid();
> +    trace_writeout_running = true;
>  
> -    thread = trace_thread_create(writeout_thread);
> -    if (!thread) {
> +    trace_writeout_thread = trace_thread_create(writeout_thread);
> +    if (!trace_writeout_thread) {
>          warn_report("unable to initialize simple trace backend");
>          return false;
>      }
>  
> +#ifndef _WIN32
> +    /* Terminate writeout thread across fork and restart it in parent and
> +     * child afterwards.
> +     */
> +    pthread_atfork(stop_writeout_thread,
> +                   restart_writeout_thread,
> +                   restart_writeout_thread);
> +#endif
> +
>      atexit(st_flush_trace_buffer);
>      return true;
>  }
> 


Reply via email to