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 "apr.h"
18 #include "apr_private.h"
19 #include "apr_general.h"
20 #include "apr_strings.h"
21 #include "apr_portable.h"
22 #include "apr_arch_file_io.h"
23 #include "apr_arch_proc_mutex.h"
24 #include "apr_arch_misc.h"
25
proc_mutex_cleanup(void * mutex_)26 static apr_status_t proc_mutex_cleanup(void *mutex_)
27 {
28 apr_proc_mutex_t *mutex = mutex_;
29
30 if (mutex->handle) {
31 if (CloseHandle(mutex->handle) == 0) {
32 return apr_get_os_error();
33 }
34 }
35 return APR_SUCCESS;
36 }
37
apr_proc_mutex_create(apr_proc_mutex_t ** mutex,const char * fname,apr_lockmech_e mech,apr_pool_t * pool)38 APR_DECLARE(apr_status_t) apr_proc_mutex_create(apr_proc_mutex_t **mutex,
39 const char *fname,
40 apr_lockmech_e mech,
41 apr_pool_t *pool)
42 {
43 HANDLE hMutex;
44 void *mutexkey;
45
46 /* res_name_from_filename turns fname into a pseduo-name
47 * without slashes or backslashes, and prepends the \global
48 * prefix on Win2K and later
49 */
50 if (fname) {
51 mutexkey = res_name_from_filename(fname, 1, pool);
52 }
53 else {
54 mutexkey = NULL;
55 }
56
57 #if APR_HAS_UNICODE_FS
58 IF_WIN_OS_IS_UNICODE
59 {
60 hMutex = CreateMutexW(NULL, FALSE, mutexkey);
61 }
62 #endif
63 #if APR_HAS_ANSI_FS
64 ELSE_WIN_OS_IS_ANSI
65 {
66 hMutex = CreateMutexA(NULL, FALSE, mutexkey);
67 }
68 #endif
69
70 if (!hMutex) {
71 return apr_get_os_error();
72 }
73
74 *mutex = (apr_proc_mutex_t *)apr_palloc(pool, sizeof(apr_proc_mutex_t));
75 (*mutex)->pool = pool;
76 (*mutex)->handle = hMutex;
77 (*mutex)->fname = fname;
78 apr_pool_cleanup_register((*mutex)->pool, *mutex,
79 proc_mutex_cleanup, apr_pool_cleanup_null);
80 return APR_SUCCESS;
81 }
82
apr_proc_mutex_child_init(apr_proc_mutex_t ** mutex,const char * fname,apr_pool_t * pool)83 APR_DECLARE(apr_status_t) apr_proc_mutex_child_init(apr_proc_mutex_t **mutex,
84 const char *fname,
85 apr_pool_t *pool)
86 {
87 HANDLE hMutex;
88 void *mutexkey;
89
90 if (!fname) {
91 /* Reinitializing unnamed mutexes is a noop in the Unix code. */
92 return APR_SUCCESS;
93 }
94
95 /* res_name_from_filename turns file into a pseudo-name
96 * without slashes or backslashes, and prepends the \global
97 * prefix on Win2K and later
98 */
99 mutexkey = res_name_from_filename(fname, 1, pool);
100
101 #if defined(_WIN32_WCE)
102 hMutex = CreateMutex(NULL, FALSE, mutexkey);
103 if (hMutex && ERROR_ALREADY_EXISTS != GetLastError()) {
104 CloseHandle(hMutex);
105 hMutex = NULL;
106 SetLastError(ERROR_FILE_NOT_FOUND);
107 }
108 #else
109 #if APR_HAS_UNICODE_FS
110 IF_WIN_OS_IS_UNICODE
111 {
112 hMutex = OpenMutexW(MUTEX_ALL_ACCESS, FALSE, mutexkey);
113 }
114 #endif
115 #if APR_HAS_ANSI_FS
116 ELSE_WIN_OS_IS_ANSI
117 {
118 hMutex = OpenMutexA(MUTEX_ALL_ACCESS, FALSE, mutexkey);
119 }
120 #endif
121 #endif
122
123 if (!hMutex) {
124 return apr_get_os_error();
125 }
126
127 *mutex = (apr_proc_mutex_t *)apr_palloc(pool, sizeof(apr_proc_mutex_t));
128 (*mutex)->pool = pool;
129 (*mutex)->handle = hMutex;
130 (*mutex)->fname = fname;
131 apr_pool_cleanup_register((*mutex)->pool, *mutex,
132 proc_mutex_cleanup, apr_pool_cleanup_null);
133 return APR_SUCCESS;
134 }
135
apr_proc_mutex_lock(apr_proc_mutex_t * mutex)136 APR_DECLARE(apr_status_t) apr_proc_mutex_lock(apr_proc_mutex_t *mutex)
137 {
138 DWORD rv;
139
140 rv = WaitForSingleObject(mutex->handle, INFINITE);
141
142 if (rv == WAIT_OBJECT_0 || rv == WAIT_ABANDONED) {
143 return APR_SUCCESS;
144 }
145 return apr_get_os_error();
146 }
147
apr_proc_mutex_trylock(apr_proc_mutex_t * mutex)148 APR_DECLARE(apr_status_t) apr_proc_mutex_trylock(apr_proc_mutex_t *mutex)
149 {
150 DWORD rv;
151
152 rv = WaitForSingleObject(mutex->handle, 0);
153
154 if (rv == WAIT_OBJECT_0 || rv == WAIT_ABANDONED) {
155 return APR_SUCCESS;
156 }
157 else if (rv == WAIT_TIMEOUT) {
158 return APR_EBUSY;
159 }
160 return apr_get_os_error();
161 }
162
apr_proc_mutex_unlock(apr_proc_mutex_t * mutex)163 APR_DECLARE(apr_status_t) apr_proc_mutex_unlock(apr_proc_mutex_t *mutex)
164 {
165 if (ReleaseMutex(mutex->handle) == 0) {
166 return apr_get_os_error();
167 }
168 return APR_SUCCESS;
169 }
170
apr_proc_mutex_destroy(apr_proc_mutex_t * mutex)171 APR_DECLARE(apr_status_t) apr_proc_mutex_destroy(apr_proc_mutex_t *mutex)
172 {
173 apr_status_t stat;
174
175 stat = proc_mutex_cleanup(mutex);
176 if (stat == APR_SUCCESS) {
177 apr_pool_cleanup_kill(mutex->pool, mutex, proc_mutex_cleanup);
178 }
179 return stat;
180 }
181
apr_proc_mutex_cleanup(void * mutex)182 APR_DECLARE(apr_status_t) apr_proc_mutex_cleanup(void *mutex)
183 {
184 return apr_proc_mutex_destroy((apr_proc_mutex_t *)mutex);
185 }
186
apr_proc_mutex_lockfile(apr_proc_mutex_t * mutex)187 APR_DECLARE(const char *) apr_proc_mutex_lockfile(apr_proc_mutex_t *mutex)
188 {
189 return mutex->fname;
190 }
191
apr_proc_mutex_name(apr_proc_mutex_t * mutex)192 APR_DECLARE(const char *) apr_proc_mutex_name(apr_proc_mutex_t *mutex)
193 {
194 return apr_proc_mutex_defname();
195 }
196
apr_proc_mutex_defname(void)197 APR_DECLARE(const char *) apr_proc_mutex_defname(void)
198 {
199 return "win32mutex";
200 }
201
202 APR_POOL_IMPLEMENT_ACCESSOR(proc_mutex)
203
204 /* Implement OS-specific accessors defined in apr_portable.h */
205
APR_DECLARE(apr_status_t)206 APR_DECLARE(apr_status_t) apr_os_proc_mutex_get(apr_os_proc_mutex_t *ospmutex,
207 apr_proc_mutex_t *mutex)
208 {
209 *ospmutex = mutex->handle;
210 return APR_SUCCESS;
211 }
212
apr_os_proc_mutex_put(apr_proc_mutex_t ** pmutex,apr_os_proc_mutex_t * ospmutex,apr_pool_t * pool)213 APR_DECLARE(apr_status_t) apr_os_proc_mutex_put(apr_proc_mutex_t **pmutex,
214 apr_os_proc_mutex_t *ospmutex,
215 apr_pool_t *pool)
216 {
217 if (pool == NULL) {
218 return APR_ENOPOOL;
219 }
220 if ((*pmutex) == NULL) {
221 (*pmutex) = (apr_proc_mutex_t *)apr_palloc(pool,
222 sizeof(apr_proc_mutex_t));
223 (*pmutex)->pool = pool;
224 }
225 (*pmutex)->handle = *ospmutex;
226 return APR_SUCCESS;
227 }
228
229