This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
[PATCH v3] Make fprintf() function to multithread-safe
- From: Peng Haitao <penght at cn dot fujitsu dot com>
- To: roland at hack dot frob dot com
- Cc: carlos at systemhalted dot org, drepper at gmail dot com, libc-alpha at sourceware dot org
- Date: Tue, 10 Jul 2012 11:34:26 +0800
- Subject: [PATCH v3] Make fprintf() function to multithread-safe
- References: <1340257789-14975-1-git-send-email-penght@cn.fujitsu.com>
fprintf() uses static variables __printf_function_table and
__printf_va_arg_table indirectly, which are not protected. It is
not safe in multithread circumstance.
When call fprintf() and register_printf_specifier() simultaneously
in multithread circumstance, the following case will cause unsafe.
The case has two threads: A and B.
a. thread B call register_printf_specifier('W', print_widget, print_widget_arginfo)
b. thread A call fprintf (stdout, "|%W|\n", &mywidget), when judge
__printf_function_table is not NULL, but not output &mywidget
c. thread B call register_printf_specifier('W', NULL, NULL)
d. thread A output &mywidget when __printf_function_table is NULL
e. programme will Segmentation fault
Signed-off-by: Peng Haitao <penght@cn.fujitsu.com>
---
ChangeLog | 12 ++++++++++++
stdio-common/reg-printf.c | 6 +++---
stdio-common/reg-type.c | 6 +++---
stdio-common/vfprintf.c | 6 ++++++
4 files changed, 24 insertions(+), 6 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 613ce75..63acfd9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,17 @@
2012-07-10 Peng Haitao <penght@cn.fujitsu.com>
+ [BZ #14267]
+ * stdio-common/reg-printf.c: __libc_lock_define_initialized changed to
+ __libc_rwlock_define_initialized.
+ Parameter 'lock' changed to global lock 'lock_fun_type'.
+ * stdio-common/reg-type.c: __libc_lock_define_initialized changed to
+ __libc_rwlock_define.
+ Parameter 'lock' changed to global lock 'lock_fun_type'.
+ * stdio-common/vfprintf.c (vfprintf): Lock around use of
+ __printf_function_table and __printf_va_arg_table.
+
+2012-07-10 Peng Haitao <penght@cn.fujitsu.com>
+
[BZ #14333]
* stdlib/cxa_atexit.c: Do not include bits/libc-lock.h.
(__libc_lock_define_initialized): Parameter 'lock' changed to global
diff --git a/stdio-common/reg-printf.c b/stdio-common/reg-printf.c
index 30bf7da..56e2b37 100644
--- a/stdio-common/reg-printf.c
+++ b/stdio-common/reg-printf.c
@@ -28,7 +28,7 @@ libc_freeres_ptr (printf_arginfo_size_function **__printf_arginfo_table)
attribute_hidden;
printf_function **__printf_function_table attribute_hidden;
-__libc_lock_define_initialized (static, lock)
+__libc_rwlock_define_initialized (, lock_fun_type);
int __register_printf_specifier (int, printf_function,
printf_arginfo_size_function);
@@ -50,7 +50,7 @@ __register_printf_specifier (spec, converter, arginfo)
}
int result = 0;
- __libc_lock_lock (lock);
+ __libc_rwlock_wrlock (lock_fun_type);
if (__printf_function_table == NULL)
{
@@ -70,7 +70,7 @@ __register_printf_specifier (spec, converter, arginfo)
__printf_arginfo_table[spec] = arginfo;
out:
- __libc_lock_unlock (lock);
+ __libc_rwlock_unlock (lock_fun_type);
return result;
}
diff --git a/stdio-common/reg-type.c b/stdio-common/reg-type.c
index 31c7472..bd55e9c 100644
--- a/stdio-common/reg-type.c
+++ b/stdio-common/reg-type.c
@@ -25,7 +25,7 @@
libc_freeres_ptr (printf_va_arg_function **__printf_va_arg_table)
attribute_hidden;
-__libc_lock_define_initialized (static, lock);
+__libc_rwlock_define (extern, lock_fun_type);
/* Last type allocated. */
static int pa_next_type = PA_LAST;
@@ -35,7 +35,7 @@ int
__register_printf_type (printf_va_arg_function fct)
{
int result = -1;
- __libc_lock_lock (lock);
+ __libc_rwlock_wrlock (lock_fun_type);
if (__printf_va_arg_table == NULL)
{
@@ -54,7 +54,7 @@ __register_printf_type (printf_va_arg_function fct)
}
out:
- __libc_lock_unlock (lock);
+ __libc_rwlock_unlock (lock_fun_type);
return result;
}
diff --git a/stdio-common/vfprintf.c b/stdio-common/vfprintf.c
index d569034..5d082cf 100644
--- a/stdio-common/vfprintf.c
+++ b/stdio-common/vfprintf.c
@@ -195,6 +195,7 @@ static CHAR_T *group_number (CHAR_T *, CHAR_T *, const char *, const char *)
__THROW internal_function;
#endif
+__libc_rwlock_define (extern, lock_fun_type);
/* The function itself. */
int
@@ -1319,6 +1320,8 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
_IO_cleanup_region_start ((void (*) (void *)) &_IO_funlockfile, s);
_IO_flockfile (s);
+ __libc_rwlock_rdlock (lock_fun_type);
+
/* Write the literal text before the first format. */
outstring ((const UCHAR_T *) format,
lead_str_end - (const UCHAR_T *) format);
@@ -2047,6 +2050,9 @@ do_positional:
all_done:
free (args_malloced);
free (workstart);
+
+ __libc_rwlock_unlock (lock_fun_type);
+
/* Unlock the stream. */
_IO_funlockfile (s);
_IO_cleanup_region_end (0);
--
1.7.10.4