Skip to content

Race condition in pplx::task_completion_event #256

Open
@mmthomas

Description

@mmthomas

It's possible for two threads to try to complete a task_completion_event at the same time, where one calls set_exception(), and the other calls set().

A problem occurs if the first thread calling _StoreException() (via set_exception()) successfully completes, storing the exception holder, but then the second thread calling set() gets its timeslice before the first thread can call _CancelInternal().

In this case, the call to set() will enter the critical section and set the stack-based _RunContinuations flag to true, which will then subsequently cause the non-empty exception holder to be released. If this is the only reference to the exception holder (set via the first thread), the process will abort in debug builds via _REPORT_PPLTASK_UNOBSERVED_EXCEPTION.

So the possible order of operations is this:

thread1...                          

    set_exception(...)
        _Cancel(...)
            if (_StoreException(...)) // returns true

thread 2...

    set(...)
        ...
        // following call reports unobserved exception, 
        // even though tce is not in a canceled state
        _M_Impl->_M_exceptionHolder.reset(); 

thread 1...      

                // following call returns false, 
                // even though _StoreException() returned true
                _Canceled = _CancelInternal(); 

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions