This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
[PATCH v4] Make fprintf() function to multithread-safe
- From: Peng Haitao <penght at cn dot fujitsu dot com>
- To: libc-alpha at sourceware dot org
- Date: Fri, 1 Mar 2013 17:47:19 +0800
- Subject: [PATCH v4] Make fprintf() function to multithread-safe
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 | 7 ++++---
stdio-common/reg-type.c | 7 ++++---
stdio-common/vfprintf.c | 7 +++++++
4 files changed, 27 insertions(+), 6 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 171e05e..bc2436c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,17 @@
2013-03-01 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.
+
+2013-03-01 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 ff68b94..3964723 100644
--- a/stdio-common/reg-printf.c
+++ b/stdio-common/reg-printf.c
@@ -1,4 +1,5 @@
/* Copyright (C) 1991-2013 Free Software Foundation, Inc.
+ Copyright 2013 FUJITSU LIMITED
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -28,7 +29,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 +51,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 +71,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 402ec06..cd12932 100644
--- a/stdio-common/reg-type.c
+++ b/stdio-common/reg-type.c
@@ -1,4 +1,5 @@
/* Copyright (C) 2009-2013 Free Software Foundation, Inc.
+ Copyright 2013 FUJITSU LIMITED
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -25,7 +26,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 +36,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 +55,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 89126d2..77da72a 100644
--- a/stdio-common/vfprintf.c
+++ b/stdio-common/vfprintf.c
@@ -1,4 +1,5 @@
/* Copyright (C) 1991-2013 Free Software Foundation, Inc.
+ Copyright 2013 FUJITSU LIMITED
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -215,6 +216,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
@@ -1306,6 +1308,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);
@@ -2034,6 +2038,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.8.1.2