1/* Licensed to the Apache Software Foundation (ASF) under one or more 2 * contributor license agreements. See the NOTICE file distributed with 3 * this work for additional information regarding copyright ownership. 4 * The ASF licenses this file to You under the Apache License, Version 2.0 5 * (the "License"); you may not use this file except in compliance with 6 * the License. You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include "testglobalmutex.h" 18#include "apr_thread_proc.h" 19#include "apr_global_mutex.h" 20#include "apr_strings.h" 21#include "apr_errno.h" 22#include "testutil.h" 23 24static void launch_child(abts_case *tc, apr_lockmech_e mech, 25 apr_proc_t *proc, apr_pool_t *p) 26{ 27 apr_procattr_t *procattr; 28 const char *args[3]; 29 apr_status_t rv; 30 31 rv = apr_procattr_create(&procattr, p); 32 APR_ASSERT_SUCCESS(tc, "Couldn't create procattr", rv); 33 34 rv = apr_procattr_io_set(procattr, APR_NO_PIPE, APR_NO_PIPE, 35 APR_NO_PIPE); 36 APR_ASSERT_SUCCESS(tc, "Couldn't set io in procattr", rv); 37 38 rv = apr_procattr_error_check_set(procattr, 1); 39 APR_ASSERT_SUCCESS(tc, "Couldn't set error check in procattr", rv); 40 41 args[0] = "globalmutexchild" EXTENSION; 42 args[1] = (const char*)apr_itoa(p, (int)mech); 43 args[2] = NULL; 44 rv = apr_proc_create(proc, TESTBINPATH "globalmutexchild" EXTENSION, args, NULL, 45 procattr, p); 46 APR_ASSERT_SUCCESS(tc, "Couldn't launch program", rv); 47} 48 49static int wait_child(abts_case *tc, apr_proc_t *proc) 50{ 51 int exitcode; 52 apr_exit_why_e why; 53 54 ABTS_ASSERT(tc, "Error waiting for child process", 55 apr_proc_wait(proc, &exitcode, &why, APR_WAIT) == APR_CHILD_DONE); 56 57 ABTS_ASSERT(tc, "child didn't terminate normally", why == APR_PROC_EXIT); 58 return exitcode; 59} 60 61/* return symbolic name for a locking meechanism */ 62static const char *mutexname(apr_lockmech_e mech) 63{ 64 switch (mech) { 65 case APR_LOCK_FCNTL: return "fcntl"; 66 case APR_LOCK_FLOCK: return "flock"; 67 case APR_LOCK_SYSVSEM: return "sysvsem"; 68 case APR_LOCK_PROC_PTHREAD: return "proc_pthread"; 69 case APR_LOCK_POSIXSEM: return "posixsem"; 70 case APR_LOCK_DEFAULT: return "default"; 71 default: return "unknown"; 72 } 73} 74 75static void test_exclusive(abts_case *tc, void *data) 76{ 77 apr_lockmech_e mech = *(apr_lockmech_e *)data; 78 apr_proc_t p1, p2, p3, p4; 79 apr_status_t rv; 80 apr_global_mutex_t *global_lock; 81 int x = 0; 82 abts_log_message("lock mechanism is: "); 83 abts_log_message(mutexname(mech)); 84 85 rv = apr_global_mutex_create(&global_lock, LOCKNAME, mech, p); 86 APR_ASSERT_SUCCESS(tc, "Error creating mutex", rv); 87 88 launch_child(tc, mech, &p1, p); 89 launch_child(tc, mech, &p2, p); 90 launch_child(tc, mech, &p3, p); 91 launch_child(tc, mech, &p4, p); 92 93 x += wait_child(tc, &p1); 94 x += wait_child(tc, &p2); 95 x += wait_child(tc, &p3); 96 x += wait_child(tc, &p4); 97 98 if (x != MAX_COUNTER) { 99 char buf[200]; 100 sprintf(buf, "global mutex '%s' failed: %d not %d", 101 mutexname(mech), x, MAX_COUNTER); 102 abts_fail(tc, buf, __LINE__); 103 } 104} 105 106abts_suite *testglobalmutex(abts_suite *suite) 107{ 108 apr_lockmech_e mech = APR_LOCK_DEFAULT; 109 110 suite = ADD_SUITE(suite) 111 abts_run_test(suite, test_exclusive, &mech); 112#if APR_HAS_POSIXSEM_SERIALIZE 113 mech = APR_LOCK_POSIXSEM; 114 abts_run_test(suite, test_exclusive, &mech); 115#endif 116#if APR_HAS_SYSVSEM_SERIALIZE 117 mech = APR_LOCK_SYSVSEM; 118 abts_run_test(suite, test_exclusive, &mech); 119#endif 120#if APR_HAS_PROC_PTHREAD_SERIALIZE 121 mech = APR_LOCK_PROC_PTHREAD; 122 abts_run_test(suite, test_exclusive, &mech); 123#endif 124#if APR_HAS_FCNTL_SERIALIZE 125 mech = APR_LOCK_FCNTL; 126 abts_run_test(suite, test_exclusive, &mech); 127#endif 128#if APR_HAS_FLOCK_SERIALIZE 129 mech = APR_LOCK_FLOCK; 130 abts_run_test(suite, test_exclusive, &mech); 131#endif 132 133 return suite; 134} 135 136