[FFmpeg-devel] [PATCH 2/2] av_lockmgr_register defines behavior on failure.

Michael Niedermayer michaelni at gmx.at
Wed Oct 1 05:16:27 CEST 2014


On Tue, Sep 30, 2014 at 07:34:28PM -0700, Manfred Georg wrote:
> Yeah, that seemed a bit odd to me....I guess I get to go correct some
> calling code.
> 
> Here is yet another update with a comment which tells you not to use a
> static mutex.
> 
> Subject: [PATCH] av_lockmgr_register defines behavior on failure.
> 
> The register function now specifies that the user callback should
> leave things in the same state that it found them on failure but
> that failure to destroy is ignored by ffmpeg.  The register
> function is also now explicit about its behavior on failure (it now
> unregisters the previous callback and destroys all mutex).
> ---
>  libavcodec/avcodec.h | 25 ++++++++++++++++---------
>  libavcodec/utils.c   | 31 +++++++++++++++++++++----------
>  2 files changed, 37 insertions(+), 19 deletions(-)
> 
> diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
> index 94e82f7..dae3612 100644
> --- a/libavcodec/avcodec.h
> +++ b/libavcodec/avcodec.h
> @@ -5120,16 +5120,23 @@ enum AVLockOp {
> 
>  /**
>   * Register a user provided lock manager supporting the operations
> - * specified by AVLockOp. mutex points to a (void *) where the
> - * lockmgr should store/get a pointer to a user allocated mutex. It's
> - * NULL upon AV_LOCK_CREATE and != NULL for all other ops.
> - *
> - * @param cb User defined callback. Note: FFmpeg may invoke calls to this
> - *           callback during the call to av_lockmgr_register().
> - *           Thus, the application must be prepared to handle that.
> + * specified by AVLockOp.  The "mutex" argument to the function points
> + * to a (void *) where the lockmgr should store/get a pointer to a user

> + * allocated mutex.  It is NULL upon AV_LOCK_CREATE and equal to the




> + * value left by the last call for all other ops.  If the lock manager
> + * is unable to perform the op then it should leave the mutex in the same
> + * state as when it was called.  However, when called with AV_LOCK_DESTROY
> + * the mutex will always be assumed to have been successfully destroyed.

> + * If av_lockmgr_register succeeds it will return 0, if it fails it will
> + * return non-zero and destroy all mutex and unregister all callbacks.

we have no positve error codes, the positive values could be used
as success like 0 giving us the ability to extend/use them for
something in the future


> + *
> + * @param cb User defined callback.  FFmpeg invokes calls to this
> + *           callback and the previously registered callback during the
> + *           call to av_lockmgr_register().  The callback will be used to
> + *           create more than one mutex each of which must be backed
> + *           by its own underlying locking mechanism (i.e. do not
> + *           use a single static object to implement your lock manager).
>   *           If cb is set to NULL the lockmgr will be unregistered.
> - *           Also note that during unregistration the previously registered
> - *           lockmgr callback may also be invoked.
>   */
>  int av_lockmgr_register(int (*cb)(void **mutex, enum AVLockOp op));
> 
> diff --git a/libavcodec/utils.c b/libavcodec/utils.c
> index 778bdc6..717c5b1 100644
> --- a/libavcodec/utils.c
> +++ b/libavcodec/utils.c
> @@ -3457,22 +3457,33 @@ AVHWAccel *av_hwaccel_next(const AVHWAccel *hwaccel)
>  int av_lockmgr_register(int (*cb)(void **mutex, enum AVLockOp op))
>  {
>      if (lockmgr_cb) {
> -        if (lockmgr_cb(&codec_mutex, AV_LOCK_DESTROY))
> -            return -1;
> -        if (lockmgr_cb(&avformat_mutex, AV_LOCK_DESTROY))
> -            return -1;
> -        codec_mutex = NULL;
> -        avformat_mutex = NULL;
> +        // There is no good way to rollback a failure to destroy the
> +        // mutex, so we ignore failures.
> +        lockmgr_cb(&codec_mutex, AV_LOCK_DESTROY);
> +        lockmgr_cb(&avformat_mutex, AV_LOCK_DESTROY);
>      }
> 
> -    lockmgr_cb = cb;
> +    lockmgr_cb = NULL;

> +    codec_mutex = NULL;
> +    avformat_mutex = NULL;

why is this moved outside "if (lockmgr_cb)" ?


> 
> -    if (lockmgr_cb) {
> -        if (lockmgr_cb(&codec_mutex, AV_LOCK_CREATE))
> +    if (cb) {
> +        void *new_codec_mutex = NULL;
> +        void *new_avformat_mutex = NULL;
> +        if (cb(&new_codec_mutex, AV_LOCK_CREATE)) {
>              return -1;
> -        if (lockmgr_cb(&avformat_mutex, AV_LOCK_CREATE))
> +        }
> +        if (cb(&new_avformat_mutex, AV_LOCK_CREATE))
> +        {
> +            // Ignore failures to destroy the newly created mutex.
> +            cb(&new_codec_mutex, AV_LOCK_DESTROY);
>              return -1;
> +        }

> +        lockmgr_cb = cb;
> +        codec_mutex = new_codec_mutex;
> +        avformat_mutex = new_avformat_mutex;

these probably should use avpriv_atomic_ptr_cas()
to ensure the values where NULL that are replaced.
this could provide usefull debug information if someone
misuses av_lockmgr_register() like calling it from 2 threads at the
same time

[...]
-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

No snowflake in an avalanche ever feels responsible. -- Voltaire
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 181 bytes
Desc: Digital signature
URL: <https://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20141001/5ca3c774/attachment.asc>


More information about the ffmpeg-devel mailing list