#460 closed defect (fixed)
Concurrency problem when destroying stream (thanks Michael Broughton)
Reported by: | bennylp | Owned by: | bennylp |
---|---|---|---|
Priority: | normal | Milestone: | release-0.9.0 |
Component: | pjmedia | Version: | trunk |
Keywords: | Cc: | ||
Backport to 1.x milestone: | Backported: |
Description
Michael Broughton wrote in pjsip list:
I am looking at two functions in stream.c: pjmedia_stream_destroy and on_rx_rtp. I am trying to figure out if the following scenario is possible:
- Thread A calls pjmedia_stream_destroy, which locks stream->jb_mutex.
- Thread B calls on_rx_rtp, which tries to lock stream->jb_mutex but cannot right away because thread A already holds the lock.
- Thread A goes about it's work and then free's stream->jb_mutex.
- Thread B, still trying to lock stream->jb_mutex, segfaults because thread A deallocated stream->jb_mutex and zeroed out the pointer.
Change History (4)
comment:1 Changed 17 years ago by bennylp
- Component changed from applications to pjmedia
- Status changed from new to assigned
- Summary changed from Concurrency problem when destroying stream to Concurrency problem when destroying stream (thanks Michael Broughton)
comment:2 Changed 17 years ago by bennylp
comment:3 Changed 17 years ago by bennylp
- Resolution set to fixed
- Status changed from assigned to closed
comment:4 Changed 17 years ago by bennylp
Additional discussions regarding on_dtmf_callback() concurrency:
We have three cases to handle:
First is processing DTMF callback while other thread is trying to destroy the stream/call. This scenario is the same as our original stream problem, so it should have been fixed by the latest patch. We wouldn't even get into the soft deadlock state as on_dtmf() callback, so we should be safe.
(this still assumes current situation where on_dtmf() callback doesn't hold any call mutexes. Once we change on_dtmf() to acquire call mutex, then yes, this would be covered by acquire_call(), i.e. one of the thread will wait until the other is done
Although, hmmm.. thinking about it again, if we implement call locking in on_dtmf() callback, actually we will get into deadlock, as media transport mutex is not included in the standard lock order!
So maybe having call lock in on_dtmf() callback is not a good idea after all).
The second case is destroying the call in the DTMF callback itself, but leaving the UDP transport alive. This scenario also should be safe.
The third case is destroying the call *and* the UDP transport in the DTMF callback. The difference between this and scenario 2 is when the UDP transport is destroyed, so is the pool associated with it, so all memory belonging to the UDP transport will be invalid after UDP transport is destroyed.
For the third scenario, it was not safe to do that, but this should have been fixed by http://trac.pjsip.org/repos/ticket/469#comment:2, I think.
Additional note: