You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@apr.apache.org by br...@apache.org on 2014/01/21 02:22:50 UTC
svn commit: r1559878 - in /apr/apr/branches/1.5.x: ./ file_io/win32/dir.c
test/testdir.c
Author: brane
Date: Tue Jan 21 01:22:50 2014
New Revision: 1559878
URL: http://svn.apache.org/r1559878
Log:
Merged rr1559873 from trunk:
Fix timing bug in parallel apr_dir_make_recursive on Windows.
* file_io/win32/dir.c
(dir_make_parent): When parent just got created, continue creating children.
(apr_dir_make_recursive): Only handle EEXIST of the requested directory as
success, not any ancestor.
Patch by: rhuijben
* test/testdir.c
(test_mkdir_recurs_parallel): New multithreaded test case.
(test_removeall): Clean up after test_mkdir_recurs_parallel.
Modified:
apr/apr/branches/1.5.x/ (props changed)
apr/apr/branches/1.5.x/file_io/win32/dir.c
apr/apr/branches/1.5.x/test/testdir.c
Propchange: apr/apr/branches/1.5.x/
------------------------------------------------------------------------------
Merged /apr/apr/trunk:r1559873
Modified: apr/apr/branches/1.5.x/file_io/win32/dir.c
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.5.x/file_io/win32/dir.c?rev=1559878&r1=1559877&r2=1559878&view=diff
==============================================================================
--- apr/apr/branches/1.5.x/file_io/win32/dir.c (original)
+++ apr/apr/branches/1.5.x/file_io/win32/dir.c Tue Jan 21 01:22:50 2014
@@ -316,8 +316,8 @@ static apr_status_t dir_make_parent(char
if (APR_STATUS_IS_ENOENT(rv)) { /* Missing an intermediate dir */
rv = dir_make_parent(path, perm, pool);
- if (rv == APR_SUCCESS) {
- rv = apr_dir_make (path, perm, pool); /* And complete the path */
+ if (rv == APR_SUCCESS || APR_STATUS_IS_EEXIST(rv)) {
+ rv = apr_dir_make(path, perm, pool); /* And complete the path */
}
}
@@ -330,28 +330,35 @@ APR_DECLARE(apr_status_t) apr_dir_make_r
apr_pool_t *pool)
{
apr_status_t rv = 0;
-
+
rv = apr_dir_make (path, perm, pool); /* Try to make PATH right out */
-
+
if (APR_STATUS_IS_ENOENT(rv)) { /* Missing an intermediate dir */
char *dir;
-
+
rv = apr_filepath_merge(&dir, "", path, APR_FILEPATH_NATIVE, pool);
- if (rv == APR_SUCCESS)
- rv = dir_make_parent(dir, perm, pool); /* Make intermediate dirs */
-
- if (rv == APR_SUCCESS)
+ if (rv != APR_SUCCESS)
+ return rv;
+
+ rv = dir_make_parent(dir, perm, pool); /* Make intermediate dirs */
+
+ if (rv == APR_SUCCESS || APR_STATUS_IS_EEXIST(rv)) {
rv = apr_dir_make (dir, perm, pool); /* And complete the path */
- }
- /*
- * It's OK if PATH exists. Timing issues can lead to the second
- * apr_dir_make being called on existing dir, therefore this check
- * has to come last.
- */
- if (APR_STATUS_IS_EEXIST(rv))
- return APR_SUCCESS;
+ if (APR_STATUS_IS_EEXIST(rv)) {
+ rv = APR_SUCCESS; /* Timing issue; see comment below */
+ }
+ }
+ }
+ else if (APR_STATUS_IS_EEXIST(rv)) {
+ /*
+ * It's OK if PATH exists. Timing issues can lead to the
+ * second apr_dir_make being called on existing dir, therefore
+ * this check has to come last.
+ */
+ rv = APR_SUCCESS;
+ }
return rv;
}
Modified: apr/apr/branches/1.5.x/test/testdir.c
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.5.x/test/testdir.c?rev=1559878&r1=1559877&r2=1559878&view=diff
==============================================================================
--- apr/apr/branches/1.5.x/test/testdir.c (original)
+++ apr/apr/branches/1.5.x/test/testdir.c Tue Jan 21 01:22:50 2014
@@ -22,6 +22,7 @@
#include "apr_errno.h"
#include "apr_general.h"
#include "apr_lib.h"
+#include "apr_thread_proc.h"
#include "testutil.h"
static void test_mkdir(abts_case *tc, void *data)
@@ -59,6 +60,60 @@ static void test_mkdir_recurs(abts_case
ABTS_INT_EQUAL(tc, APR_DIR, finfo.filetype);
}
+static void *APR_THREAD_FUNC thread_mkdir_func(apr_thread_t *thd, void *data)
+{
+ abts_case *tc = data;
+ apr_status_t s1, s2, s3, s4, s5;
+
+ s1 = apr_dir_make_recursive("data/prll/one/thwo/three",
+ APR_FPROT_UREAD | APR_FPROT_UWRITE | APR_FPROT_UEXECUTE,
+ p);
+ s2 = apr_dir_make_recursive("data/prll/four/five/six/seven/eight",
+ APR_FPROT_UREAD | APR_FPROT_UWRITE | APR_FPROT_UEXECUTE,
+ p);
+ s3 = apr_dir_make_recursive("data/prll/nine/ten",
+ APR_FPROT_UREAD | APR_FPROT_UWRITE | APR_FPROT_UEXECUTE,
+ p);
+ s4 = apr_dir_make_recursive("data/prll/11/12/13/14/15/16/17/18/19/20",
+ APR_FPROT_UREAD | APR_FPROT_UWRITE | APR_FPROT_UEXECUTE,
+ p);
+ s5 = apr_dir_make_recursive("data/fortytwo",
+ APR_FPROT_UREAD | APR_FPROT_UWRITE | APR_FPROT_UEXECUTE,
+ p);
+
+ ABTS_INT_EQUAL(tc, APR_SUCCESS, s1);
+ ABTS_INT_EQUAL(tc, APR_SUCCESS, s2);
+ ABTS_INT_EQUAL(tc, APR_SUCCESS, s3);
+ ABTS_INT_EQUAL(tc, APR_SUCCESS, s4);
+ ABTS_INT_EQUAL(tc, APR_SUCCESS, s5);
+ return NULL;
+}
+
+static void test_mkdir_recurs_parallel(abts_case *tc, void *data)
+{
+ apr_thread_t *t1, *t2, *t3, *t4;
+ apr_status_t s1, s2, s3, s4;
+
+ s1 = apr_thread_create(&t1, NULL, thread_mkdir_func, tc, p);
+ ABTS_INT_EQUAL(tc, APR_SUCCESS, s1);
+ s2 = apr_thread_create(&t2, NULL, thread_mkdir_func, tc, p);
+ ABTS_INT_EQUAL(tc, APR_SUCCESS, s2);
+ s3 = apr_thread_create(&t3, NULL, thread_mkdir_func, tc, p);
+ ABTS_INT_EQUAL(tc, APR_SUCCESS, s3);
+ s4 = apr_thread_create(&t4, NULL, thread_mkdir_func, tc, p);
+ ABTS_INT_EQUAL(tc, APR_SUCCESS, s4);
+
+ apr_thread_join(&s1, t1);
+ apr_thread_join(&s2, t2);
+ apr_thread_join(&s3, t3);
+ apr_thread_join(&s4, t4);
+
+ ABTS_INT_EQUAL(tc, APR_SUCCESS, s1);
+ ABTS_INT_EQUAL(tc, APR_SUCCESS, s2);
+ ABTS_INT_EQUAL(tc, APR_SUCCESS, s3);
+ ABTS_INT_EQUAL(tc, APR_SUCCESS, s4);
+}
+
static void test_remove(abts_case *tc, void *data)
{
apr_status_t rv;
@@ -91,6 +146,72 @@ static void test_removeall(abts_case *tc
rv = apr_dir_remove("data/one", p);
ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+ rv = apr_dir_remove("data/prll/one/thwo/three", p);
+ ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+ rv = apr_dir_remove("data/prll/one/thwo", p);
+ ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+ rv = apr_dir_remove("data/prll/one", p);
+ ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+ rv = apr_dir_remove("data/prll/four/five/six/seven/eight", p);
+ ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+ rv = apr_dir_remove("data/prll/four/five/six/seven", p);
+ ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+ rv = apr_dir_remove("data/prll/four/five/six", p);
+ ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+ rv = apr_dir_remove("data/prll/four/five", p);
+ ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+ rv = apr_dir_remove("data/prll/four", p);
+ ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+ rv = apr_dir_remove("data/prll/nine/ten", p);
+ ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+ rv = apr_dir_remove("data/prll/nine", p);
+ ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+ rv = apr_dir_remove("data/prll/11/12/13/14/15/16/17/18/19/20", p);
+ ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+ rv = apr_dir_remove("data/prll/11/12/13/14/15/16/17/18/19", p);
+ ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+ rv = apr_dir_remove("data/prll/11/12/13/14/15/16/17/18", p);
+ ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+ rv = apr_dir_remove("data/prll/11/12/13/14/15/16/17", p);
+ ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+ rv = apr_dir_remove("data/prll/11/12/13/14/15/16", p);
+ ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+ rv = apr_dir_remove("data/prll/11/12/13/14/15", p);
+ ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+ rv = apr_dir_remove("data/prll/11/12/13/14", p);
+ ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+ rv = apr_dir_remove("data/prll/11/12/13", p);
+ ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+ rv = apr_dir_remove("data/prll/11/12", p);
+ ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+ rv = apr_dir_remove("data/prll/11", p);
+ ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+ rv = apr_dir_remove("data/prll", p);
+ ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+ rv = apr_dir_remove("data/fortytwo", p);
+ ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
}
static void test_remove_notthere(abts_case *tc, void *data)
@@ -245,6 +366,7 @@ abts_suite *testdir(abts_suite *suite)
abts_run_test(suite, test_mkdir, NULL);
abts_run_test(suite, test_mkdir_recurs, NULL);
+ abts_run_test(suite, test_mkdir_recurs_parallel, NULL);
abts_run_test(suite, test_remove, NULL);
abts_run_test(suite, test_removeall_fail, NULL);
abts_run_test(suite, test_removeall, NULL);