[PATCH] libc: make I/O locking cancel-safe with futexes
Filippo ARCIDIACONO
filippo.arcidiacono at st.com
Fri Sep 28 05:45:12 UTC 2012
Could someone take a look?
Further details could be found at
https://bugzilla.stlinux.com/show_bug.cgi?id=21083
there is also a test case spotting the issue.
> -----Original Message-----
> From: Carmelo AMOROSO [mailto:carmelo.amoroso at st.com]
> Sent: Wednesday, September 12, 2012 4:55 PM
> To: uclibc at uclibc.org
> Cc: Filippo ARCIDIACONO; Carmelo Amoroso
> Subject: [PATCH] libc: make I/O locking cancel-safe with futexes
>
> From: Filippo ARCIDIACONO <filippo.arcidiacono at st.com>
>
> Current implementation of I/O locking macros using futexes are not
> cancel safe, as if a thread is cancelled while doing IO operations,
> it does not release the lock on the IO stream. So following
> attempts to acquire the IO stream's lock would dead-lock.
> In order to make it cancel-safe, it needs to rely upon the
> pthread_cleanup push & pop protocol, as it is already done for
> the pthread_mutex counterpart.
>
> Signed-off-by: Filippo Arcidiacono <filippo.arcidiacono at st.com>
> Signed-off-by: Carmelo Amoroso <carmelo.amoroso at st.com>
> ---
> libc/stdio/Makefile.in | 3 ++
> libc/stdio/io_lock_unlock.c | 16 ++++++++++++++
> libc/sysdeps/linux/common/bits/uClibc_mutex.h | 23 +++++++++++++---
> ----
> libpthread/nptl/sysdeps/pthread/bits/stdio-lock.h | 2 +
> 4 files changed, 36 insertions(+), 8 deletions(-)
> create mode 100644 libc/stdio/io_lock_unlock.c
>
> diff --git a/libc/stdio/Makefile.in b/libc/stdio/Makefile.in
> index ff77bcb..4652036 100644
> --- a/libc/stdio/Makefile.in
> +++ b/libc/stdio/Makefile.in
> @@ -52,6 +52,9 @@ endif
>
> # pthread functions
> CSRC += flockfile.c ftrylockfile.c funlockfile.c
> +ifeq ($(UCLIBC_HAS_STDIO_FUTEXES),y)
> +CSRC += io_lock_unlock.c
> +endif
>
> # Functions with unlocked versions
> CUSRC := \
> diff --git a/libc/stdio/io_lock_unlock.c b/libc/stdio/io_lock_unlock.c
> new file mode 100644
> index 0000000..b414264
> --- /dev/null
> +++ b/libc/stdio/io_lock_unlock.c
> @@ -0,0 +1,16 @@
> +/*
> + * Copyright (C) 2012 STMicroelectronics, Ltd
> + *
> + * Author(s): Filippo Arcidiacono <filippo.arcidiacono at st.com>
> + *
> + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball
> + */
> +
> +#include <bits/stdio-lock.h>
> +
> +/* Function wrapper needed for I/O locking macros. */
> +
> +void IO_lock_unlock (_IO_lock_t *lock)
> +{
> + _IO_lock_unlock (*lock);
> +}
> diff --git a/libc/sysdeps/linux/common/bits/uClibc_mutex.h
> b/libc/sysdeps/linux/common/bits/uClibc_mutex.h
> index 94597e8..c2a1cc1 100644
> --- a/libc/sysdeps/linux/common/bits/uClibc_mutex.h
> +++ b/libc/sysdeps/linux/common/bits/uClibc_mutex.h
> @@ -12,6 +12,7 @@
>
> #ifdef __UCLIBC_HAS_THREADS__
>
> +
> #include <pthread.h>
> #ifdef _LIBC
> #include <bits/uClibc_pthread.h>
> @@ -79,15 +80,21 @@
> #define __UCLIBC_IO_MUTEX_INIT(M) _IO_lock_t M =
> _IO_lock_initializer
> #define __UCLIBC_IO_MUTEX_EXTERN(M) extern _IO_lock_t M
>
> -#define __UCLIBC_IO_MUTEX_CONDITIONAL_LOCK(M,C) \
> - if (C) {
> \
> - _IO_lock_lock(M);
> \
> - }
> +#define __UCLIBC_IO_MUTEX_CONDITIONAL_LOCK(M,C)
> \
> + do {
> \
> + struct _pthread_cleanup_buffer
> __infunc_pthread_cleanup_buffer; \
> + int __infunc_need_locking = (C);
> \
> + if (__infunc_need_locking) {
> \
> +
> _pthread_cleanup_push_defer(&__infunc_pthread_cleanup_buffer
> , \
> + (void (*) (void
> *))IO_lock_unlock, \
> + &(M));
> \
> + _IO_lock_lock((M));
> \
> + }
> \
> + ((void)0)
> +
>
> -#define __UCLIBC_IO_MUTEX_CONDITIONAL_UNLOCK(M,C) \
> - if (C) {
> \
> - _IO_lock_unlock(M);
> \
> - }
> +#define __UCLIBC_IO_MUTEX_CONDITIONAL_UNLOCK(M,C)
> \
> + __UCLIBC_MUTEX_CONDITIONAL_UNLOCK(M,C)
>
> #define __UCLIBC_IO_MUTEX_AUTO_LOCK(M,A,V) \
> __UCLIBC_IO_MUTEX_CONDITIONAL_LOCK(M,((A=(V))) ==
> 0)
> diff --git a/libpthread/nptl/sysdeps/pthread/bits/stdio-lock.h
> b/libpthread/nptl/sysdeps/pthread/bits/stdio-lock.h
> index 3437e61..c742644 100644
> --- a/libpthread/nptl/sysdeps/pthread/bits/stdio-lock.h
> +++ b/libpthread/nptl/sysdeps/pthread/bits/stdio-lock.h
> @@ -29,6 +29,8 @@
>
> typedef struct { int lock; int cnt; void *owner; } _IO_lock_t;
>
> +void IO_lock_unlock (_IO_lock_t *lock);
> +
> #define _IO_lock_initializer { LLL_LOCK_INITIALIZER, 0, NULL }
>
> #define _IO_lock_init(_name) \
> --
> 1.7.4.4
More information about the uClibc
mailing list