From 58b578c9b07497496fedd51f3aa3bd434a0fa305 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Zurcher?= Date: Wed, 20 Nov 2013 10:19:16 +0100 Subject: [PATCH] eina: fix a possible race condition during eina_file_close. replay 7e8fb93 without the breakage --- ChangeLog | 4 ++++ NEWS | 3 ++- src/lib/eina/eina_file_common.c | 9 ++++++--- src/tests/eina/eina_test_file.c | 34 +++++++++++++++++++++++++++++++++ 4 files changed, 46 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3dc7c28258..6c3dea3a93 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2013-11-20 Cedric Bail + + * Eina: Fix a possible race condition during eina_file_close. + 2013-11-19 Tom Hacohen * Evas textblock: Fixed order of tags inserted with markup_app/prepend. diff --git a/NEWS b/NEWS index 6a1f8bdb01..5ce9bcf17b 100644 --- a/NEWS +++ b/NEWS @@ -268,7 +268,8 @@ Fixes: - Fix memory leak in eina_xattr_value_ls. - Fix magic failure in eina_value_array_count when array has not been allocated. - Fix issue when wchar_t is signed and eina_unicode does negative array lookups. - - Eina: fix eina_file_map_lines() to not drop of one character in the last line. + - Fix eina_file_map_lines() to not drop of one character in the last line. + - Fix a possible race condition during eina_file_close(). * Eet: - Fix PPC (big endian) image codec bug. - Fix leak in eet_pbkdf2_sha1 with OpenSSL. diff --git a/src/lib/eina/eina_file_common.c b/src/lib/eina/eina_file_common.c index 7b05b3b249..7f83c87774 100644 --- a/src/lib/eina/eina_file_common.c +++ b/src/lib/eina/eina_file_common.c @@ -451,17 +451,20 @@ eina_file_close(Eina_File *file) EINA_SAFETY_ON_NULL_RETURN(file); + eina_lock_take(&_eina_file_lock_cache); + eina_lock_take(&file->lock); file->refcount--; if (file->refcount == 0) leave = EINA_FALSE; eina_lock_release(&file->lock); - if (leave) return; - - eina_lock_take(&_eina_file_lock_cache); + if (leave) goto end; eina_hash_del(_eina_file_cache, file->filename, file); + + // Backend specific file resource close eina_file_real_close(file); + end: eina_lock_release(&_eina_file_lock_cache); } diff --git a/src/tests/eina/eina_test_file.c b/src/tests/eina/eina_test_file.c index f2f322550f..e8f735d3f0 100644 --- a/src/tests/eina/eina_test_file.c +++ b/src/tests/eina/eina_test_file.c @@ -441,6 +441,39 @@ START_TEST(eina_test_file_virtualize) } END_TEST +static void * +_eina_test_file_thread(void *data EINA_UNUSED, Eina_Thread t EINA_UNUSED) +{ + Eina_File *f; + unsigned int i; + + for (i = 0; i < 10000; ++i) + { + f = eina_file_open("/bin/sh", EINA_FALSE); + fail_if(!f); + eina_file_close(f); + } + + return NULL; +} + +START_TEST(eina_test_file_thread) +{ + Eina_Thread th[4]; + unsigned int i; + + fail_if(!eina_init()); + + for (i = 0; i < 4; i++) + fail_if(!(eina_thread_create(&th[i], EINA_THREAD_NORMAL, 0, _eina_test_file_thread, NULL))); + + for (i = 0; i < 4; i++) + fail_if(eina_thread_join(th[i]) != NULL); + + eina_shutdown(); +} +END_TEST + void eina_test_file(TCase *tc) { @@ -449,5 +482,6 @@ eina_test_file(TCase *tc) tcase_add_test(tc, eina_file_ls_simple); tcase_add_test(tc, eina_file_map_new_test); tcase_add_test(tc, eina_test_file_virtualize); + tcase_add_test(tc, eina_test_file_thread); }