1 /***
2 This file is part of PulseAudio.
3
4 Copyright 2009 Lennart Poettering
5
6 PulseAudio is free software; you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License as published
8 by the Free Software Foundation; either version 2.1 of the License,
9 or (at your option) any later version.
10
11 PulseAudio is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License
17 along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
18 ***/
19
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23
24 #include <unistd.h>
25
26 #include <pulsecore/atomic.h>
27 #include <pulsecore/macro.h>
28
29 #include "fork-detect.h"
30
pa_detect_fork(void)31 int pa_detect_fork(void) {
32 static pa_atomic_t pid = PA_ATOMIC_INIT((int) -1);
33
34 /* Some really stupid applications (Hey, vim, that means you!)
35 * love to fork after initializing
36 * gtk/libcanberra/pulseaudio. This is really bad style. We
37 * however have to deal with this cleanly, so we try to detect the
38 * forks making sure all our calls fail cleanly after the fork. */
39
40 pa_assert_cc(sizeof(pa_atomic_t) >= sizeof(pid_t));
41
42 for (;;) {
43 pid_t stored_pid = (pid_t) pa_atomic_load(&pid);
44
45 /* First let's check whether the current pid matches the stored one */
46 if (stored_pid == getpid())
47 return false;
48
49 /* Does it contain a different PID than ours? Then the process got forked. */
50 if ((int) stored_pid != (int) -1)
51 return true;
52
53 /* Ok, it still contains no PID, then store it */
54 if (pa_atomic_cmpxchg(&pid, (int) -1, (int) getpid()))
55 return false;
56 }
57 }
58