]> git.proxmox.com Git - mirror_lxc.git/blame - src/lxc/lxclock.c
Merge pull request #1539 from brauner/2017-05-06/fix_abstract_unix_sockets
[mirror_lxc.git] / src / lxc / lxclock.c
CommitLineData
72d0e1cb
SG
1/* liblxcapi
2 *
3 * Copyright © 2012 Serge Hallyn <serge.hallyn@ubuntu.com>.
4 * Copyright © 2012 Canonical Ltd.
5 *
d75462e4
SH
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
72d0e1cb
SG
19 */
20
052616eb 21#define _GNU_SOURCE
72d0e1cb
SG
22#include "lxclock.h"
23#include <malloc.h>
8173e600 24#include <stdio.h>
df271a59
SH
25#include <errno.h>
26#include <unistd.h>
93dc5327 27#include <fcntl.h>
469b5787 28#include <stdlib.h>
052616eb 29#include <pthread.h>
f2363e38 30
5cee8c50 31#include <lxc/lxccontainer.h>
72d0e1cb 32
f2363e38
ÇO
33#include "utils.h"
34#include "log.h"
35
41f68357
ÇO
36#ifdef MUTEX_DEBUGGING
37#include <execinfo.h>
38#endif
39
5b28d063
SH
40#define MAX_STACKDEPTH 25
41
72d0e1cb
SG
42#define OFLAG (O_CREAT | O_RDWR)
43#define SEMMODE 0660
44#define SEMVALUE 1
45#define SEMVALUE_LOCKED 0
72d0e1cb 46
df271a59 47lxc_log_define(lxc_lock, lxc);
72d0e1cb 48
052616eb 49#ifdef MUTEX_DEBUGGING
74a3920a 50static pthread_mutex_t thread_mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
41f68357 51
74a3920a 52static inline void dump_stacktrace(void)
41f68357
ÇO
53{
54 void *array[MAX_STACKDEPTH];
55 size_t size;
56 char **strings;
57 size_t i;
58
59 size = backtrace(array, MAX_STACKDEPTH);
60 strings = backtrace_symbols(array, size);
61
62 // Using fprintf here as our logging module is not thread safe
63 fprintf(stderr, "\tObtained %zd stack frames.\n", size);
64
65 for (i = 0; i < size; i++)
66 fprintf(stderr, "\t\t%s\n", strings[i]);
67
68 free (strings);
69}
052616eb 70#else
74a3920a 71static pthread_mutex_t thread_mutex = PTHREAD_MUTEX_INITIALIZER;
41f68357 72
74a3920a 73static inline void dump_stacktrace(void) {;}
052616eb 74#endif
df271a59 75
74a3920a 76static void lock_mutex(pthread_mutex_t *l)
41f68357
ÇO
77{
78 int ret;
79
80 if ((ret = pthread_mutex_lock(l)) != 0) {
03fadd16 81 fprintf(stderr, "pthread_mutex_lock returned:%d %s\n", ret, strerror(ret));
41f68357
ÇO
82 dump_stacktrace();
83 exit(1);
84 }
85}
86
74a3920a 87static void unlock_mutex(pthread_mutex_t *l)
41f68357
ÇO
88{
89 int ret;
90
91 if ((ret = pthread_mutex_unlock(l)) != 0) {
03fadd16 92 fprintf(stderr, "pthread_mutex_unlock returned:%d %s\n", ret, strerror(ret));
41f68357
ÇO
93 dump_stacktrace();
94 exit(1);
95 }
96}
97
df271a59 98static char *lxclock_name(const char *p, const char *n)
72d0e1cb
SG
99{
100 int ret;
469b5787
SH
101 int len;
102 char *dest;
44b9ae4b 103 char *rundir;
71b0fed6 104
469b5787 105 /* lockfile will be:
72cf81f6 106 * "/run" + "/lxc/lock/$lxcpath/$lxcname + '\0' if root
469b5787 107 * or
72cf81f6 108 * $XDG_RUNTIME_DIR + "/lxc/lock/$lxcpath/$lxcname + '\0' if non-root
469b5787
SH
109 */
110
72cf81f6
SH
111 /* length of "/lxc/lock/" + $lxcpath + "/" + "." + $lxcname + '\0' */
112 len = strlen("/lxc/lock/") + strlen(n) + strlen(p) + 3;
9e60f51d 113 rundir = get_rundir();
97a696c6
SG
114 if (!rundir)
115 return NULL;
469b5787
SH
116 len += strlen(rundir);
117
44b9ae4b
SG
118 if ((dest = malloc(len)) == NULL) {
119 free(rundir);
72d0e1cb 120 return NULL;
44b9ae4b 121 }
469b5787 122
72cf81f6 123 ret = snprintf(dest, len, "%s/lxc/lock/%s", rundir, p);
72d0e1cb
SG
124 if (ret < 0 || ret >= len) {
125 free(dest);
44b9ae4b 126 free(rundir);
72d0e1cb
SG
127 return NULL;
128 }
5cee8c50 129 ret = mkdir_p(dest, 0755);
5cee8c50 130 if (ret < 0) {
72cf81f6
SH
131 free(dest);
132 free(rundir);
133 return NULL;
134 }
72d0e1cb 135
72cf81f6 136 ret = snprintf(dest, len, "%s/lxc/lock/%s/.%s", rundir, p, n);
44b9ae4b 137 free(rundir);
df271a59
SH
138 if (ret < 0 || ret >= len) {
139 free(dest);
140 return NULL;
141 }
142 return dest;
72d0e1cb
SG
143}
144
145static sem_t *lxc_new_unnamed_sem(void)
146{
87677950
SH
147 sem_t *s;
148 int ret;
72d0e1cb 149
87677950
SH
150 s = malloc(sizeof(*s));
151 if (!s)
152 return NULL;
153 ret = sem_init(s, 0, 1);
bdb539b8
SH
154 if (ret) {
155 free(s);
87677950 156 return NULL;
bdb539b8 157 }
87677950 158 return s;
72d0e1cb
SG
159}
160
df271a59 161struct lxc_lock *lxc_newlock(const char *lxcpath, const char *name)
72d0e1cb 162{
df271a59 163 struct lxc_lock *l;
72d0e1cb 164
df271a59
SH
165 l = malloc(sizeof(*l));
166 if (!l)
167 goto out;
72d0e1cb 168
df271a59
SH
169 if (!name) {
170 l->type = LXC_LOCK_ANON_SEM;
171 l->u.sem = lxc_new_unnamed_sem();
41c3b7c7
DE
172 if (!l->u.sem) {
173 free(l);
174 l = NULL;
175 }
df271a59
SH
176 goto out;
177 }
178
179 l->type = LXC_LOCK_FLOCK;
180 l->u.f.fname = lxclock_name(lxcpath, name);
181 if (!l->u.f.fname) {
182 free(l);
183 l = NULL;
184 goto out;
185 }
186 l->u.f.fd = -1;
187
188out:
df271a59 189 return l;
72d0e1cb
SG
190}
191
df271a59 192int lxclock(struct lxc_lock *l, int timeout)
72d0e1cb 193{
5cee8c50 194 int ret = -1, saved_errno = errno;
93dc5327 195 struct flock lk;
72d0e1cb 196
df271a59
SH
197 switch(l->type) {
198 case LXC_LOCK_ANON_SEM:
199 if (!timeout) {
200 ret = sem_wait(l->u.sem);
201 if (ret == -1)
202 saved_errno = errno;
203 } else {
204 struct timespec ts;
205 if (clock_gettime(CLOCK_REALTIME, &ts) == -1) {
206 ret = -2;
207 goto out;
208 }
209 ts.tv_sec += timeout;
210 ret = sem_timedwait(l->u.sem, &ts);
211 if (ret == -1)
212 saved_errno = errno;
213 }
214 break;
215 case LXC_LOCK_FLOCK:
216 ret = -2;
217 if (timeout) {
218 ERROR("Error: timeout not supported with flock");
219 ret = -2;
220 goto out;
221 }
222 if (!l->u.f.fname) {
223 ERROR("Error: filename not set for flock");
224 ret = -2;
225 goto out;
226 }
227 if (l->u.f.fd == -1) {
228 l->u.f.fd = open(l->u.f.fname, O_RDWR|O_CREAT,
229 S_IWUSR | S_IRUSR);
230 if (l->u.f.fd == -1) {
231 ERROR("Error opening %s", l->u.f.fname);
232 goto out;
233 }
234 }
93dc5327
SH
235 lk.l_type = F_WRLCK;
236 lk.l_whence = SEEK_SET;
237 lk.l_start = 0;
238 lk.l_len = 0;
239 ret = fcntl(l->u.f.fd, F_SETLKW, &lk);
df271a59
SH
240 if (ret == -1)
241 saved_errno = errno;
242 break;
72d0e1cb
SG
243 }
244
df271a59 245out:
df271a59 246 errno = saved_errno;
72d0e1cb
SG
247 return ret;
248}
249
df271a59 250int lxcunlock(struct lxc_lock *l)
72d0e1cb 251{
5cee8c50 252 int ret = 0, saved_errno = errno;
93dc5327 253 struct flock lk;
df271a59
SH
254
255 switch(l->type) {
256 case LXC_LOCK_ANON_SEM:
257 if (!l->u.sem)
258 ret = -2;
659aa061 259 else {
df271a59
SH
260 ret = sem_post(l->u.sem);
261 saved_errno = errno;
659aa061 262 }
df271a59
SH
263 break;
264 case LXC_LOCK_FLOCK:
265 if (l->u.f.fd != -1) {
93dc5327
SH
266 lk.l_type = F_UNLCK;
267 lk.l_whence = SEEK_SET;
268 lk.l_start = 0;
269 lk.l_len = 0;
270 ret = fcntl(l->u.f.fd, F_SETLK, &lk);
271 if (ret < 0)
df271a59
SH
272 saved_errno = errno;
273 close(l->u.f.fd);
274 l->u.f.fd = -1;
275 } else
276 ret = -2;
277 break;
278 }
279
df271a59
SH
280 errno = saved_errno;
281 return ret;
282}
283
5cee8c50
SH
284/*
285 * lxc_putlock() is only called when a container_new() fails,
286 * or during container_put(), which is already guaranteed to
287 * only be done by one task.
288 * So the only exclusion we need to provide here is for regular
289 * thread safety (i.e. file descriptor table changes).
290 */
df271a59
SH
291void lxc_putlock(struct lxc_lock *l)
292{
df271a59 293 if (!l)
5cee8c50 294 return;
df271a59
SH
295 switch(l->type) {
296 case LXC_LOCK_ANON_SEM:
41c3b7c7 297 if (l->u.sem) {
527dacf6 298 sem_destroy(l->u.sem);
41c3b7c7
DE
299 free(l->u.sem);
300 l->u.sem = NULL;
301 }
df271a59
SH
302 break;
303 case LXC_LOCK_FLOCK:
304 if (l->u.f.fd != -1) {
305 close(l->u.f.fd);
306 l->u.f.fd = -1;
307 }
f10fad2f
ME
308 free(l->u.f.fname);
309 l->u.f.fname = NULL;
df271a59
SH
310 break;
311 }
41c3b7c7 312 free(l);
5cee8c50
SH
313}
314
025ed0f3 315void process_lock(void)
5cee8c50 316{
41f68357 317 lock_mutex(&thread_mutex);
5cee8c50
SH
318}
319
320void process_unlock(void)
321{
41f68357
ÇO
322 unlock_mutex(&thread_mutex);
323}
052616eb 324
67c4fe9b 325/* One thread can do fork() while another one is holding a mutex.
ec64264d 326 * There is only one thread in child just after the fork(), so no one will ever release that mutex.
67c4fe9b
SG
327 * We setup a "child" fork handler to unlock the mutex just after the fork().
328 * For several mutex types, unlocking an unlocked mutex can lead to undefined behavior.
329 * One way to deal with it is to setup "prepare" fork handler
330 * to lock the mutex before fork() and both "parent" and "child" fork handlers
331 * to unlock the mutex.
332 * This forbids doing fork() while explicitly holding the lock.
333 */
babbea4b 334#ifdef HAVE_PTHREAD_ATFORK
67c4fe9b
SG
335__attribute__((constructor))
336static void process_lock_setup_atfork(void)
337{
338 pthread_atfork(process_lock, process_unlock, process_unlock);
339}
babbea4b 340#endif
67c4fe9b 341
5cee8c50
SH
342int container_mem_lock(struct lxc_container *c)
343{
344 return lxclock(c->privlock, 0);
345}
346
347void container_mem_unlock(struct lxc_container *c)
348{
349 lxcunlock(c->privlock);
350}
351
352int container_disk_lock(struct lxc_container *c)
353{
354 int ret;
355
356 if ((ret = lxclock(c->privlock, 0)))
357 return ret;
358 if ((ret = lxclock(c->slock, 0))) {
359 lxcunlock(c->privlock);
360 return ret;
361 }
362 return 0;
363}
364
365void container_disk_unlock(struct lxc_container *c)
366{
367 lxcunlock(c->slock);
368 lxcunlock(c->privlock);
369}