]>
Commit | Line | Data |
---|---|---|
e5fd101c PS |
1 | autofs-5.0.4 - library reload fix update |
2 | ||
3 | From: Ian Kent <raven@themaw.net> | |
4 | ||
5 | We still have a problem with libxml2 being unloaded before its thread | |
6 | specific data destructor is called. This is due to the main thread | |
7 | exiting (closing the handle we hold open to prevent this) before all | |
8 | the mount handling threads have actually completed. This patch makes | |
9 | the mount handling threads joinable (and joins with them as they exit) | |
10 | to ensure that the mount handling threads have completed before allowing | |
11 | the main thread to complete. | |
12 | --- | |
13 | ||
14 | daemon/automount.c | 35 +++++++++++++++++++++++------------ | |
15 | daemon/direct.c | 7 ++++--- | |
16 | daemon/indirect.c | 7 ++++--- | |
17 | daemon/state.c | 7 ++++--- | |
18 | include/master.h | 3 +++ | |
19 | lib/master.c | 38 ++++++++++++++++++++++++++++++++++---- | |
20 | modules/mount_autofs.c | 4 ++-- | |
21 | 7 files changed, 74 insertions(+), 27 deletions(-) | |
22 | ||
23 | ||
24 | diff --git a/daemon/automount.c b/daemon/automount.c | |
25 | index e120f50..f04273f 100644 | |
26 | --- a/daemon/automount.c | |
27 | +++ b/daemon/automount.c | |
28 | @@ -69,8 +69,9 @@ static size_t kpkt_len; | |
29 | /* Does kernel know about SOCK_CLOEXEC and friends */ | |
30 | static int cloexec_works = 0; | |
31 | ||
32 | -/* Attribute to create detached thread */ | |
33 | -pthread_attr_t thread_attr; | |
34 | +/* Attributes for creating detached and joinable threads */ | |
35 | +pthread_attr_t th_attr; | |
36 | +pthread_attr_t th_attr_detached; | |
37 | ||
38 | struct master_readmap_cond mrc = { | |
39 | PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, 0, NULL, 0, 0, 0, 0}; | |
40 | @@ -1192,7 +1193,7 @@ static pthread_t do_signals(struct master *master, int sig) | |
41 | if (status) | |
42 | fatal(status); | |
43 | ||
44 | - status = pthread_create(&thid, &thread_attr, do_notify_state, &r_sig); | |
45 | + status = pthread_create(&thid, &th_attr_detached, do_notify_state, &r_sig); | |
46 | if (status) { | |
47 | error(master->logopt, | |
48 | "mount state notify thread create failed"); | |
49 | @@ -1281,7 +1282,7 @@ static int do_hup_signal(struct master *master, time_t age) | |
50 | ||
51 | master->reading = 1; | |
52 | ||
53 | - status = pthread_create(&thid, &thread_attr, do_read_master, NULL); | |
54 | + status = pthread_create(&thid, &th_attr_detached, do_read_master, NULL); | |
55 | if (status) { | |
56 | error(logopt, | |
57 | "master read map thread create failed"); | |
58 | @@ -1327,7 +1328,7 @@ static void *statemachine(void *arg) | |
59 | case SIGTERM: | |
60 | case SIGINT: | |
61 | case SIGUSR2: | |
62 | - if (master_list_empty(master_list)) | |
63 | + if (master_done(master_list)) | |
64 | return NULL; | |
65 | case SIGUSR1: | |
66 | do_signals(master_list, sig); | |
67 | @@ -1448,8 +1449,6 @@ static void handle_mounts_cleanup(void *arg) | |
68 | master_mutex_unlock(); | |
69 | ||
70 | destroy_logpri_fifo(ap); | |
71 | - master_free_mapent_sources(ap->entry, 1); | |
72 | - master_free_mapent(ap->entry); | |
73 | ||
74 | if (clean) { | |
75 | if (rmdir(path) == -1) { | |
76 | @@ -1461,8 +1460,12 @@ static void handle_mounts_cleanup(void *arg) | |
77 | ||
78 | info(logopt, "shut down path %s", path); | |
79 | ||
80 | - /* If we are the last tell the state machine to shutdown */ | |
81 | - if (!submount && master_list_empty(master_list)) | |
82 | + /* | |
83 | + * If we are not a submount send a signal to the signal handler | |
84 | + * so it can join with any completed handle_mounts() threads and | |
85 | + * perform final cleanup. | |
86 | + */ | |
87 | + if (!submount) | |
88 | pthread_kill(state_mach_thid, SIGTERM); | |
89 | ||
90 | return; | |
91 | @@ -1980,7 +1983,15 @@ int main(int argc, char *argv[]) | |
92 | exit(1); | |
93 | } | |
94 | ||
95 | - if (pthread_attr_init(&thread_attr)) { | |
96 | + if (pthread_attr_init(&th_attr)) { | |
97 | + logerr("%s: failed to init thread attribute struct!", | |
98 | + program); | |
99 | + close(start_pipefd[1]); | |
100 | + release_flag_file(); | |
101 | + exit(1); | |
102 | + } | |
103 | + | |
104 | + if (pthread_attr_init(&th_attr_detached)) { | |
105 | logerr("%s: failed to init thread attribute struct!", | |
106 | program); | |
107 | close(start_pipefd[1]); | |
108 | @@ -1989,7 +2000,7 @@ int main(int argc, char *argv[]) | |
109 | } | |
110 | ||
111 | if (pthread_attr_setdetachstate( | |
112 | - &thread_attr, PTHREAD_CREATE_DETACHED)) { | |
113 | + &th_attr_detached, PTHREAD_CREATE_DETACHED)) { | |
114 | logerr("%s: failed to set detached thread attribute!", | |
115 | program); | |
116 | close(start_pipefd[1]); | |
117 | @@ -1999,7 +2010,7 @@ int main(int argc, char *argv[]) | |
118 | ||
119 | #ifdef _POSIX_THREAD_ATTR_STACKSIZE | |
120 | if (pthread_attr_setstacksize( | |
121 | - &thread_attr, PTHREAD_STACK_MIN*64)) { | |
122 | + &th_attr_detached, PTHREAD_STACK_MIN*64)) { | |
123 | logerr("%s: failed to set stack size thread attribute!", | |
124 | program); | |
125 | close(start_pipefd[1]); | |
126 | diff --git a/daemon/direct.c b/daemon/direct.c | |
127 | index c0243c4..d9dda3d 100644 | |
128 | --- a/daemon/direct.c | |
129 | +++ b/daemon/direct.c | |
130 | @@ -37,7 +37,8 @@ | |
131 | ||
132 | #include "automount.h" | |
133 | ||
134 | -extern pthread_attr_t thread_attr; | |
135 | +/* Attribute to create detached thread */ | |
136 | +extern pthread_attr_t th_attr_detached; | |
137 | ||
138 | struct mnt_params { | |
139 | char *options; | |
140 | @@ -1142,7 +1143,7 @@ int handle_packet_expire_direct(struct autofs_point *ap, autofs_packet_expire_di | |
141 | debug(ap->logopt, "token %ld, name %s", | |
142 | (unsigned long) pkt->wait_queue_token, mt->name); | |
143 | ||
144 | - status = pthread_create(&thid, &thread_attr, do_expire_direct, mt); | |
145 | + status = pthread_create(&thid, &th_attr_detached, do_expire_direct, mt); | |
146 | if (status) { | |
147 | error(ap->logopt, "expire thread create failed"); | |
148 | ops->send_fail(ap->logopt, | |
149 | @@ -1451,7 +1452,7 @@ int handle_packet_missing_direct(struct autofs_point *ap, autofs_packet_missing_ | |
150 | mt->gid = pkt->gid; | |
151 | mt->wait_queue_token = pkt->wait_queue_token; | |
152 | ||
153 | - status = pthread_create(&thid, &thread_attr, do_mount_direct, mt); | |
154 | + status = pthread_create(&thid, &th_attr_detached, do_mount_direct, mt); | |
155 | if (status) { | |
156 | error(ap->logopt, "missing mount thread create failed"); | |
157 | ops->send_fail(ap->logopt, | |
158 | diff --git a/daemon/indirect.c b/daemon/indirect.c | |
159 | index 9d3745c..0721707 100644 | |
160 | --- a/daemon/indirect.c | |
161 | +++ b/daemon/indirect.c | |
162 | @@ -36,7 +36,8 @@ | |
163 | ||
164 | #include "automount.h" | |
165 | ||
166 | -extern pthread_attr_t thread_attr; | |
167 | +/* Attribute to create detached thread */ | |
168 | +extern pthread_attr_t th_attr_detached; | |
169 | ||
170 | static pthread_mutex_t ea_mutex = PTHREAD_MUTEX_INITIALIZER; | |
171 | ||
172 | @@ -647,7 +648,7 @@ int handle_packet_expire_indirect(struct autofs_point *ap, autofs_packet_expire_ | |
173 | mt->len = pkt->len; | |
174 | mt->wait_queue_token = pkt->wait_queue_token; | |
175 | ||
176 | - status = pthread_create(&thid, &thread_attr, do_expire_indirect, mt); | |
177 | + status = pthread_create(&thid, &th_attr_detached, do_expire_indirect, mt); | |
178 | if (status) { | |
179 | error(ap->logopt, "expire thread create failed"); | |
180 | ops->send_fail(ap->logopt, | |
181 | @@ -835,7 +836,7 @@ int handle_packet_missing_indirect(struct autofs_point *ap, autofs_packet_missin | |
182 | mt->gid = pkt->gid; | |
183 | mt->wait_queue_token = pkt->wait_queue_token; | |
184 | ||
185 | - status = pthread_create(&thid, &thread_attr, do_mount_indirect, mt); | |
186 | + status = pthread_create(&thid, &th_attr_detached, do_mount_indirect, mt); | |
187 | if (status) { | |
188 | error(ap->logopt, "expire thread create failed"); | |
189 | ops->send_fail(ap->logopt, | |
190 | diff --git a/daemon/state.c b/daemon/state.c | |
191 | index 87c16a6..cd63be1 100644 | |
192 | --- a/daemon/state.c | |
193 | +++ b/daemon/state.c | |
194 | @@ -16,7 +16,8 @@ | |
195 | ||
196 | #include "automount.h" | |
197 | ||
198 | -extern pthread_attr_t thread_attr; | |
199 | +/* Attribute to create detached thread */ | |
200 | +extern pthread_attr_t th_attr_detached; | |
201 | ||
202 | struct state_queue { | |
203 | pthread_t thid; | |
204 | @@ -292,7 +293,7 @@ static enum expire expire_proc(struct autofs_point *ap, int now) | |
205 | else | |
206 | expire = expire_proc_direct; | |
207 | ||
208 | - status = pthread_create(&thid, &thread_attr, expire, ea); | |
209 | + status = pthread_create(&thid, &th_attr_detached, expire, ea); | |
210 | if (status) { | |
211 | error(ap->logopt, | |
212 | "expire thread create for %s failed", ap->path); | |
213 | @@ -519,7 +520,7 @@ static unsigned int st_readmap(struct autofs_point *ap) | |
214 | ra->ap = ap; | |
215 | ra->now = now; | |
216 | ||
217 | - status = pthread_create(&thid, &thread_attr, do_readmap, ra); | |
218 | + status = pthread_create(&thid, &th_attr_detached, do_readmap, ra); | |
219 | if (status) { | |
220 | error(ap->logopt, "read map thread create failed"); | |
221 | st_readmap_cleanup(ra); | |
222 | diff --git a/include/master.h b/include/master.h | |
223 | index 6d801a9..c519e97 100644 | |
224 | --- a/include/master.h | |
225 | +++ b/include/master.h | |
226 | @@ -48,6 +48,7 @@ struct master_mapent { | |
227 | struct map_source *maps; | |
228 | struct autofs_point *ap; | |
229 | struct list_head list; | |
230 | + struct list_head join; | |
231 | }; | |
232 | ||
233 | struct master { | |
234 | @@ -61,6 +62,7 @@ struct master { | |
235 | unsigned int logopt; | |
236 | struct mapent_cache *nc; | |
237 | struct list_head mounts; | |
238 | + struct list_head completed; | |
239 | }; | |
240 | ||
241 | /* From the yacc master map parser */ | |
242 | @@ -109,6 +111,7 @@ void master_notify_state_change(struct master *, int); | |
243 | int master_mount_mounts(struct master *, time_t, int); | |
244 | extern inline unsigned int master_get_logopt(void); | |
245 | int master_list_empty(struct master *); | |
246 | +int master_done(struct master *); | |
247 | int master_kill(struct master *); | |
248 | ||
249 | #endif | |
250 | diff --git a/lib/master.c b/lib/master.c | |
251 | index e1cc062..762094f 100644 | |
252 | --- a/lib/master.c | |
253 | +++ b/lib/master.c | |
254 | @@ -32,8 +32,8 @@ struct master *master_list = NULL; | |
255 | ||
256 | extern long global_negative_timeout; | |
257 | ||
258 | -/* Attribute to create detached thread */ | |
259 | -extern pthread_attr_t thread_attr; | |
260 | +/* Attribute to create a joinable thread */ | |
261 | +extern pthread_attr_t th_attr; | |
262 | ||
263 | extern struct startup_cond suc; | |
264 | ||
265 | @@ -704,11 +704,16 @@ void master_add_mapent(struct master *master, struct master_mapent *entry) | |
266 | ||
267 | void master_remove_mapent(struct master_mapent *entry) | |
268 | { | |
269 | + struct master *master = entry->master; | |
270 | + | |
271 | if (entry->ap->submount) | |
272 | return; | |
273 | ||
274 | - if (!list_empty(&entry->list)) | |
275 | + if (!list_empty(&entry->list)) { | |
276 | list_del_init(&entry->list); | |
277 | + list_add(&entry->join, &master->completed); | |
278 | + } | |
279 | + | |
280 | return; | |
281 | } | |
282 | ||
283 | @@ -786,6 +791,7 @@ struct master *master_new(const char *name, unsigned int timeout, unsigned int g | |
284 | master->logopt = master->default_logging; | |
285 | ||
286 | INIT_LIST_HEAD(&master->mounts); | |
287 | + INIT_LIST_HEAD(&master->completed); | |
288 | ||
289 | return master; | |
290 | } | |
291 | @@ -993,7 +999,7 @@ static int master_do_mount(struct master_mapent *entry) | |
292 | ||
293 | debug(ap->logopt, "mounting %s", entry->path); | |
294 | ||
295 | - status = pthread_create(&thid, &thread_attr, handle_mounts, &suc); | |
296 | + status = pthread_create(&thid, &th_attr, handle_mounts, &suc); | |
297 | if (status) { | |
298 | crit(ap->logopt, | |
299 | "failed to create mount handler thread for %s", | |
300 | @@ -1170,6 +1176,30 @@ int master_list_empty(struct master *master) | |
301 | return res; | |
302 | } | |
303 | ||
304 | +int master_done(struct master *master) | |
305 | +{ | |
306 | + struct list_head *head, *p; | |
307 | + struct master_mapent *entry; | |
308 | + int res = 0; | |
309 | + | |
310 | + master_mutex_lock(); | |
311 | + head = &master->completed; | |
312 | + p = head->next; | |
313 | + while (p != head) { | |
314 | + entry = list_entry(p, struct master_mapent, join); | |
315 | + p = p->next; | |
316 | + list_del(&entry->join); | |
317 | + pthread_join(entry->thid, NULL); | |
318 | + master_free_mapent_sources(entry, 1); | |
319 | + master_free_mapent(entry); | |
320 | + } | |
321 | + if (list_empty(&master->mounts)) | |
322 | + res = 1; | |
323 | + master_mutex_unlock(); | |
324 | + | |
325 | + return res; | |
326 | +} | |
327 | + | |
328 | inline unsigned int master_get_logopt(void) | |
329 | { | |
330 | return master_list ? master_list->logopt : LOGOPT_NONE; | |
331 | diff --git a/modules/mount_autofs.c b/modules/mount_autofs.c | |
332 | index 82a5ef3..44fc043 100644 | |
333 | --- a/modules/mount_autofs.c | |
334 | +++ b/modules/mount_autofs.c | |
335 | @@ -30,7 +30,7 @@ | |
336 | #define MODPREFIX "mount(autofs): " | |
337 | ||
338 | /* Attribute to create detached thread */ | |
339 | -extern pthread_attr_t thread_attr; | |
340 | +extern pthread_attr_t th_attr_detached; | |
341 | extern struct startup_cond suc; | |
342 | ||
343 | int mount_version = AUTOFS_MOUNT_VERSION; /* Required by protocol */ | |
344 | @@ -235,7 +235,7 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, | |
345 | suc.done = 0; | |
346 | suc.status = 0; | |
347 | ||
348 | - if (pthread_create(&thid, &thread_attr, handle_mounts, &suc)) { | |
349 | + if (pthread_create(&thid, &th_attr_detached, handle_mounts, &suc)) { | |
350 | crit(ap->logopt, | |
351 | MODPREFIX | |
352 | "failed to create mount handler thread for %s", |