mq_send()/mq_receive() may never return if used from threads

Christian Franke Christian.Franke@t-online.de
Fri Jan 17 15:56:59 GMT 2025


Found with 'stress-ng --workload ...':

If mq_receive is called on an empty queue and mq_send is called later 
from a different thread, both functions never return and signals 
(including SIGKILL) are no longer processed.

Testcase (attached):

$ uname -r
3.5.5-1.x86_64

$ gcc -o mqhang mqhang.c

$ ./mqhang
mq_send...
mq_send = 0
mq_receive...
mq_receive = 8
mq_receive...
mq_send...
[...hangs...]

Problem does not occur if mq_receive() is called from a fork()ed process 
instead of a thread.

-- 
Regards,
Christian

-------------- next part --------------
#include <fcntl.h>
#include <mqueue.h>
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>

static void *receiver(void *arg)
{
  mqd_t mq = *(mqd_t*)arg;
  unsigned prio;
  char msg[42];
  for (int i = 0; i < 2; i++) {
    if (i == 0)
      sleep(2);
    printf("mq_receive...\n"); fflush(stdout);
    ssize_t ret = mq_receive(mq, msg, sizeof(msg), &prio);
    printf("mq_receive = %zd\n", ret); fflush(stdout);
  
  }
  return NULL;
}

int main()
{
  const char mq_name[] = "/mqtest";
  struct mq_attr attr = { 0, 10, 42, 0 };
  mqd_t mq = mq_open(mq_name, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR, &attr);
  if (mq == (mqd_t)-1) {
    perror("mq_open"); return 1;
  }

  pthread_t t;
  if (pthread_create(&t, NULL, receiver, &mq)) {
    fprintf(stderr, "pthread_create failed\n"); return 1;
  }

  const char msg[] = "Message";
  for (int i = 0; i < 2; i++) {
    if (i == 1)
      sleep(5);
    printf("mq_send...\n"); fflush(stdout);
    int ret = mq_send(mq, msg, sizeof(msg), 0);
    printf("mq_send = %d\n", ret); fflush(stdout);
  }

  pthread_join(t, NULL);
  mq_close(mq);
  mq_unlink(mq_name); // Fails, see separate post
  return 0;
}


More information about the Cygwin mailing list