This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
[PATCH v2] Make fprintf() function to multithread-safe
- From: Peng Haitao <penght at cn dot fujitsu dot com>
- To: schwab at linux-m68k dot org
- Cc: drepper at gmail dot com, libc-alpha at sourceware dot org
- Date: Thu, 21 Jun 2012 13:49:49 +0800
- Subject: [PATCH v2] Make fprintf() function to multithread-safe
- References: <m2fw9qmm78.fsf@igel.home>
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 | 5 +++++
stdio-common/reg-printf.c | 6 +++---
stdio-common/reg-type.c | 6 +++---
stdio-common/vfprintf.c | 6 ++++++
4 files changed, 17 insertions(+), 6 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 102ccba..429c632 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2012-06-21 Peng Haitao <penght@cn.fujitsu.com>
+
+ * stdio-common/vfprintf.c (vfprintf): Lock around use of
+ __printf_function_table and __printf_va_arg_table.
+
2012-06-18 H.J. Lu <hongjiu.lu@intel.com>
[BZ #14117]
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.2