1
0

mq_notify.c 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  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. struct args {
  9. pthread_barrier_t barrier;
  10. int sock;
  11. const struct sigevent *sev;
  12. };
  13. static void *start(void *p)
  14. {
  15. struct args *args = p;
  16. char buf[32];
  17. ssize_t n;
  18. int s = args->sock;
  19. void (*func)(union sigval) = args->sev->sigev_notify_function;
  20. union sigval val = args->sev->sigev_value;
  21. pthread_barrier_wait(&args->barrier);
  22. n = recv(s, buf, sizeof(buf), MSG_NOSIGNAL|MSG_WAITALL);
  23. close(s);
  24. if (n==sizeof buf && buf[sizeof buf - 1] == 1)
  25. func(val);
  26. return 0;
  27. }
  28. int mq_notify(mqd_t mqd, const struct sigevent *sev)
  29. {
  30. struct args args = { .sev = sev };
  31. pthread_attr_t attr;
  32. pthread_t td;
  33. int s;
  34. struct sigevent sev2;
  35. static const char zeros[32];
  36. if (!sev || sev->sigev_notify != SIGEV_THREAD)
  37. return syscall(SYS_mq_notify, mqd, sev);
  38. s = socket(AF_NETLINK, SOCK_RAW|SOCK_CLOEXEC, 0);
  39. if (s < 0) return -1;
  40. args.sock = s;
  41. if (sev->sigev_notify_attributes) attr = *sev->sigev_notify_attributes;
  42. else pthread_attr_init(&attr);
  43. pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
  44. pthread_barrier_init(&args.barrier, 0, 2);
  45. if (pthread_create(&td, &attr, start, &args)) {
  46. __syscall(SYS_close, s);
  47. errno = EAGAIN;
  48. return -1;
  49. }
  50. pthread_barrier_wait(&args.barrier);
  51. pthread_barrier_destroy(&args.barrier);
  52. sev2.sigev_notify = SIGEV_THREAD;
  53. sev2.sigev_signo = s;
  54. sev2.sigev_value.sival_ptr = (void *)&zeros;
  55. if (syscall(SYS_mq_notify, mqd, &sev2) < 0) {
  56. pthread_cancel(td);
  57. __syscall(SYS_close, s);
  58. return -1;
  59. }
  60. return 0;
  61. }