Solved No mq_unlink?

unitrunker

Well-Known Member

Reaction score: 134
Messages: 404

Is valgrind running on the Linux api?

 
OP
P

Paul Floyd

Member

Reaction score: 22
Messages: 96

The regression test is failing standalone. No Valgrind, no Linux.

The code is below. config.h is that of Valgrind, but I guess it only defines HAVE_MQUEUE_H in this case.

C:
#include <config.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>

#ifdef HAVE_MQUEUE_H

#include <mqueue.h>

#define MSGMAX 10
#define MSGSIZEMAX 1024

int main(int argc, char **argv)
{
  struct mq_attr mqa;
  mqd_t mqdw;
  mqd_t mqdr;
  char buffer[MSGSIZEMAX];
  unsigned int priority;
  int len;

  mqa.mq_maxmsg = MSGMAX;
  mqa.mq_msgsize = MSGSIZEMAX;

  if ((mqdw = mq_open("/valgrind-mqueue", O_CREAT|O_EXCL|O_WRONLY, 0600, &mqa)) < 0)
    {
      if (errno == ENOSYS)
        exit(0);
      perror("mq_open");
      exit(1);
    }

  if ((mqdr = mq_open("/valgrind-mqueue", O_RDONLY)) < 0)
    {
      perror("mq_open");
      mq_unlink("/valgrind-mqueue");
      mq_close(mqdw);
      exit(1);
    }

  if (mq_unlink("/valgrind-mqueue") < 0)
    {
      perror("mq_unlink");
      mq_close(mqdw);
      mq_close(mqdr);
      exit(1);
    }

  if (mq_send(mqdw, "PING", 4, 0) < 0)
    {
      perror("mq_send");
      mq_close(mqdr);
      mq_close(mqdw);
      exit(1);
    }

  if ((len = mq_receive(mqdr, buffer, sizeof(buffer), &priority)) < 0)
    {
      perror("mq_receive");
      mq_close(mqdr);
      mq_close(mqdw);
      exit(1);
    }

#if !defined(VGO_solaris)
  /* On Solaris, there is no existing notification registration. */
  if (mq_notify(mqdr, NULL) < 0)
    {
      perror("mq_notify");
      mq_close(mqdr);
      mq_close(mqdw);
      exit(1);
    }
#endif /* !VGO_solaris */

  if (len != 4 || memcmp(buffer, "PING", 4) != 0)
    {
      fprintf(stderr, "Message corrupt!");
    }

  if (mq_getattr(mqdr, &mqa) < 0)
    {
      perror("mq_getattr");
      mq_close(mqdr);
      mq_close(mqdw);
      exit(1);
    }

  if (mq_setattr(mqdw, &mqa, &mqa) < 0)
    {
      perror("mq_setattr");
      mq_close(mqdr);
      mq_close(mqdw);
      exit(1);
    }

  if (mq_close(mqdr) < 0)
    {
      perror("mq_close");
      mq_close(mqdw);
      exit(1);
    }

  if (mq_close(mqdw) < 0)
    {
      perror("mq_close");
      exit(1);
    }

  exit(0);
}

#else

int main(int argc, char **argv)
{
  exit(0);
}

#endif
 

unitrunker

Well-Known Member

Reaction score: 134
Messages: 404

A comment in the code by the author to explain the need to unlink while two mq descriptors are open - would be nice.
 
OP
P

Paul Floyd

Member

Reaction score: 22
Messages: 96

I know nothing about mq. Open and unlink is a common idiom when using regular files. I will check but I expect that, given the nature of the error message, mq_unlink won't work for any state of the queue.
 

mark_j

Well-Known Member

Reaction score: 124
Messages: 378

If these tests are failing because mq_unlink is not a freebsd system call (though freebsd supports some parts of message queue) then you either need to provide a replacement or not run the tests.

I don't know much about valgrind other than it's 99.9% focussed on linux; that ought tell you something.
Don't they have a port to Darwin? See what they do on that platform?
 
OP
P

Paul Floyd

Member

Reaction score: 22
Messages: 96

If these tests are failing because mq_unlink is not a freebsd system call (though freebsd supports some parts of message queue) then you either need to provide a replacement or not run the tests.

I don't know much about valgrind other than it's 99.9% focussed on linux; that ought tell you something.
Don't they have a port to Darwin? See what they do on that platform?
I'll probably #ifdef out the mq_unlink in this regtest. mq_unlink is there in librt. On the kernel side it looks like it ought to be there. Perhaps a bug or an omission? I'll take a look at macOS.

As for Valgrind, I do know a bit about it. I'd go as far as to say that Linux x86/amd64 is the only 1st class citizen. Solaris was fairly solid, but hasn't been maintained in a while. The macOS port hasn't been keeping up with Apple releases. I'm making slow but steady progress on getting the FreeBSD version up to a decent state (see here).
 

unitrunker

Well-Known Member

Reaction score: 134
Messages: 404

I wrote some trivial posix mq code a year or so ago. The default queue depth is 10. mq_unlink definitely works.
 
OP
P

Paul Floyd

Member

Reaction score: 22
Messages: 96

Maybe a year or so ago, but not now. In the end I just #ifdefed out the code and the test now passes.
 

unitrunker

Well-Known Member

Reaction score: 134
Messages: 404

I just tried this.

# kldload mqueuefs
# mount -t mqueuefs null /mnt/mqueue

I use mq_open with O_CREAT to create a queue "/orange".

# ls /mnt/mqueue
orange

Run a short program that calls mq_unlink - the return value is zero (success) and "orange" disappears.

This is 12.1-RELEASE.

The only funny thing is 'man mq_unlink' comes up empty.
 
OP
P

Paul Floyd

Member

Reaction score: 22
Messages: 96

OK thanks. I didn't load the mq kernel module. It seems odd that all of the other functions work. Maybe in the long term I'll see if autoconf can detect the functionality of mq_unlink.
 
OP
P

Paul Floyd

Member

Reaction score: 22
Messages: 96

And finally

Code:
paulf> perl tests/vg_regtest */tests/mq
mq:              valgrind   ./mq

== 1 test, 0 stderr failures, 0 stdout failures, 0 stderrB failures, 0 stdoutB failures, 0 post failures ==
Needed to load the mq kernel module and add quite a few fixes to the mq syscalls in Valgrind.
 
Top