fix longstanding missing static in mq_notify (namespace pollution)
[musl] / src / mq / mq_notify.c
1 #include <mqueue.h>
2 #include <pthread.h>
3 #include <errno.h>
4 #include <sys/socket.h>
5 #include <signal.h>
6 #include <unistd.h>
7 #include "syscall.h"
8
9 struct args {
10         pthread_barrier_t barrier;
11         int sock;
12         const struct sigevent *sev;
13 };
14
15 static void *start(void *p)
16 {
17         struct args *args = p;
18         char buf[32];
19         ssize_t n;
20         int s = args->sock;
21         void (*func)(union sigval) = args->sev->sigev_notify_function;
22         union sigval val = args->sev->sigev_value;
23
24         pthread_barrier_wait(&args->barrier);
25         n = recv(s, buf, sizeof(buf), MSG_NOSIGNAL|MSG_WAITALL);
26         close(s);
27         if (n==sizeof buf && buf[sizeof buf - 1] == 1)
28                 func(val);
29         return 0;
30 }
31
32 int mq_notify(mqd_t mqd, const struct sigevent *sev)
33 {
34         struct args args = { .sev = sev };
35         pthread_attr_t attr;
36         pthread_t td;
37         int s;
38         struct sigevent sev2;
39         static const char zeros[32];
40
41         if (!sev || sev->sigev_notify != SIGEV_THREAD)
42                 return syscall(SYS_mq_notify, mqd, sev);
43
44         s = socket(AF_NETLINK, SOCK_RAW|SOCK_CLOEXEC, 0);
45         if (s < 0) return -1;
46         args.sock = s;
47
48         if (sev->sigev_notify_attributes) attr = *sev->sigev_notify_attributes;
49         else pthread_attr_init(&attr);
50         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
51         pthread_barrier_init(&args.barrier, 0, 2);
52
53         if (pthread_create(&td, &attr, start, &args)) {
54                 __syscall(SYS_close, s);
55                 errno = EAGAIN;
56                 return -1;
57         }
58
59         pthread_barrier_wait(&args.barrier);
60         pthread_barrier_destroy(&args.barrier);
61
62         sev2.sigev_notify = SIGEV_THREAD;
63         sev2.sigev_signo = s;
64         sev2.sigev_value.sival_ptr = (void *)&zeros;
65
66         if (syscall(SYS_mq_notify, mqd, &sev2) < 0) {
67                 pthread_cancel(td);
68                 __syscall(SYS_close, s);
69                 return -1;
70         }
71
72         return 0;
73 }