Recent

Author Topic: msgrcv only succeeds if msgsnd sends a buffer with only zeros.  (Read 1009 times)

TCH

  • Full Member
  • ***
  • Posts: 184
I have two processes, which have these lines:
Code: Pascal  [Select][+][-]
  1. msgp.mtype := 1;
  2. e := msgsnd(msqid, @msgp, 4, IPC_NOWAIT);
and
Code: Pascal  [Select][+][-]
  1. sz := msgrcv(msqid, @msgp, 4, 1, IPC_NOWAIT);
The variable msgp is the type of
Code: Pascal  [Select][+][-]
  1. type mymsg1 = record
  2.         mtype: longword;
  3.         mtext: array[0..7] of byte;
  4. end;
Now, msgsnd() always reports no problems, that the buffer is sent. However, msgrcv() always gives back -1 with errno of ESysENOMSG, except if the first four byte of msgp.mtext are zeros. Then it succeeds, else it fails. Regardless the size of the sent buffer.

The very same algorithm and code works flawlessly with C. Any ideas?

TCH

  • Full Member
  • ***
  • Posts: 184
Re: msgrcv only succeeds if msgsnd sends a buffer with only zeros.
« Reply #1 on: May 17, 2022, 11:58:24 am »
No ideas?

MarkMLl

  • Hero Member
  • *****
  • Posts: 4422
Re: msgrcv only succeeds if msgsnd sends a buffer with only zeros.
« Reply #2 on: May 17, 2022, 12:13:49 pm »
What library are you using? How is the socket opened?

Give us a compilable example to demonstrate the problem.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 10079
  • FPC developer.
Re: msgrcv only succeeds if msgsnd sends a buffer with only zeros.
« Reply #3 on: May 17, 2022, 01:31:09 pm »
  • OS
  • compiler target and version
  • c code
  • pascal code

MarkMLl

  • Hero Member
  • *****
  • Posts: 4422
Re: msgrcv only succeeds if msgsnd sends a buffer with only zeros.
« Reply #4 on: May 17, 2022, 02:09:15 pm »
If we really are obliged to read minds, I suggest that https://linux.die.net/man/2/msgrcv might be relevant, which *explicitly* says:

Code: Text  [Select][+][-]
  1. The msgp argument is a pointer to caller-defined structure of the following
  2. general form:
  3.  
  4.     struct msgbuf {
  5.         long mtype;       /* message type, must be > 0 */
  6.         char mtext[1];    /* message data */
  7.     };
  8.  
  9. The mtext field is an array (or other structure) whose size is specified by
  10. msgsz, a nonnegative integer value. Messages of zero length (i.e., no
  11. mtext field) are permitted. The mtype field must have a strictly positive
  12. integer value. This value can be used by the receiving process for message
  13. selection (see the description of msgrcv() below).
  14.  

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

TCH

  • Full Member
  • ***
  • Posts: 184
Re: msgrcv only succeeds if msgsnd sends a buffer with only zeros.
« Reply #5 on: May 18, 2022, 06:36:02 pm »
I use no library and i open no socket. The OS is Linux AMD64, the target is the same. The FPC is of version 3.2.2 The C and Pascal code are here:
http://oscomp.hu/depot/msgtest.c
http://oscomp.hu/depot/msgtest.pas
And i've read the manual; the C code works as intended. But in the Pascal code, only a longint of zero can be transmitted, all else will yield a result of -1 and ESysENOMSG in errno (fpgeterrno).

MarkMLl

  • Hero Member
  • *****
  • Posts: 4422
Re: msgrcv only succeeds if msgsnd sends a buffer with only zeros.
« Reply #6 on: May 18, 2022, 06:47:45 pm »
I use no library and i open no socket. The OS is Linux AMD64, the target is the same. The FPC is of version 3.2.2 The C and Pascal code are here:
http://oscomp.hu/depot/msgtest.c
http://oscomp.hu/depot/msgtest.pas
And i've read the manual; the C code works as intended. But in the Pascal code, only a longint of zero can be transmitted, all else will yield a result of -1 and ESysENOMSG in errno (fpgeterrno).

You are using the Pascal ipc library as documented at https://www.freepascal.org/docs-html/current/rtl/ipc/index-5.html.

I suggest you start off with the example give there, without making any assumptions that it is directly compatible with the low-level unix API.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

TCH

  • Full Member
  • ***
  • Posts: 184
Re: msgrcv only succeeds if msgsnd sends a buffer with only zeros.
« Reply #7 on: May 18, 2022, 07:26:35 pm »
Isn't that a unit? Also, even if it's not compatible with the UNIX API, why does it work with a buffer of zeros and not elseway? This is the most basic existing usage: one send and one receive. It should work.
Besides i need to be compatible with the UNIX API. The programs will not necessarily be all written in Pascal. Maybe either process will be C, the other will be Pascal. (Not this one example.)
« Last Edit: May 18, 2022, 07:32:18 pm by TCH »

Lutz Mändle

  • Jr. Member
  • **
  • Posts: 62
Re: msgrcv only succeeds if msgsnd sends a buffer with only zeros.
« Reply #8 on: May 20, 2022, 12:32:21 am »
Hi,
in your demo program change message type record to:
Code: Pascal  [Select][+][-]
  1. type mymsg_t = record
  2.         mtype: clong;
  3.         mtext: array[0..7] of byte;
  4. end;
  5.  

Also change the line
Code: Pascal  [Select][+][-]
  1.         msqid := msgget(IPC_PRIVATE, 0600 or IPC_CREAT);
to
Code: Pascal  [Select][+][-]
  1.         msqid := msgget(IPC_PRIVATE, &0600 or IPC_CREAT);

Then it works.


TCH

  • Full Member
  • ***
  • Posts: 184
Re: msgrcv only succeeds if msgsnd sends a buffer with only zeros.
« Reply #9 on: May 20, 2022, 09:18:36 am »
Changing the type of mtype from longword to int64 did the trick, thank you very much!
You are right about the missing & character too, but that was only a mistake in the example code i provided here; in the actual code, the & was there to sign the octal representation: the erroneous type caused the problem.

I don't get this though. These functions are calling the libc functions, aren't they? (At least according to packages/rtl-extra/src/unix/ipc.pp:656, or FPC_USE_LIBC is not set?) The needed structure should be identical and the C versions use 32-bit for that field everywhere...

MarkMLl

  • Hero Member
  • *****
  • Posts: 4422
Re: msgrcv only succeeds if msgsnd sends a buffer with only zeros.
« Reply #10 on: May 20, 2022, 09:33:49 am »
These functions are calling the libc functions, aren't they?

Not a safe assumption in the general case. Libc is called by some stuff but my understanding is that FPC tries to avoid it as much as possible; even when it does call it you can find that there are unexpected changes e.g. what libc would expect to be a zero-terminated string is now a Pascal-type string.

You /can/ go direct to the syscalls or low-level kernel libraries, but it's very easy to fall foul of e.g. alignment issues.

So the first thing to do is *always* test the example provided in a package first, then to read the documentation, then to look at the wiki, and finally to start writing your own code.

But I'm as bad as anybody at trying to bypass some of those steps :-)

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

TCH

  • Full Member
  • ***
  • Posts: 184
Re: msgrcv only succeeds if msgsnd sends a buffer with only zeros.
« Reply #11 on: May 20, 2022, 09:45:00 am »
I was to follow FP guidelines, but i was deceived by Wikipedia where it was told, that long is 32-bit. But that turned out to be erroneous, it is 64-bit on 64-bit OS-es.
The FreePascal manual says however, that clong is always 64-bit. Does that mean, that if FPC_USE_LIBC is set, then these functions will fail if the TMSGbuf derivate is defined with clong as mtype?

MarkMLl

  • Hero Member
  • *****
  • Posts: 4422
Re: msgrcv only succeeds if msgsnd sends a buffer with only zeros.
« Reply #12 on: May 20, 2022, 09:52:45 am »
I was to follow FP guidelines, but i was deceived by Wikipedia where it was told, that long is 32-bit. But that turned out to be erroneous, it is 64-bit on 64-bit OS-es.
The FreePascal manual says however, that clong is always 64-bit. Does that mean, that if FPC_USE_LIBC is set, then these functions will fail if the TMSGbuf derivate is defined with clong as mtype?

Well, that's your fault for relying on Wikipedia and on other random URLs. But using a random URL also give me this:

https://fpc-pascal.freepascal.narkive.com/3JsSIyvf/usage-of-fpc-use-libc

So the bottom line is that if you rebuilt FPC you might be able to use it... and the core developers would probably be interested in your experience.

But I say again:

* Test programs. If one of these doesn't work as expected raise a bug.

* Documentation. If this is incomplete discuss it here or on the MLs.

* FPC/Lazarus wiki (and I /don't/ mean Wikipedia here). If this is wrong fix it.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

TCH

  • Full Member
  • ***
  • Posts: 184
Re: msgrcv only succeeds if msgsnd sends a buffer with only zeros.
« Reply #13 on: May 20, 2022, 10:27:18 am »
Well, that's your fault for relying on Wikipedia and on other random URLs. But using a random URL also give me this:
And if i would relying on the FPC documentation, then would it be my fault too, if i would have ended up the same position, but from a different angle?
The FPC manual is actually erroneously states, that clong is int64. I've just compiled the test program on a 32-bit Linux, with the mtype as int64. It produced the same error as before. If i change it back to longword, then it works perfectly. So, it needs to be 32-bit on 32-bit OS and 64-bit on 64-bit OS. With clong, it works on both. Therefore the bitwidth of clong also depends on the bitwidth of the underlying arch and thus the FPC manual is erroneous.

MarkMLl

  • Hero Member
  • *****
  • Posts: 4422
Re: msgrcv only succeeds if msgsnd sends a buffer with only zeros.
« Reply #14 on: May 20, 2022, 10:37:29 am »
The FPC manual is actually erroneously states, that clong is int64.

I agree, raise it as a bug.

Code: Pascal  [Select][+][-]
  1.      52 {$ifdef cpu64}
  2.      53   clong                  = int64;              pclong                 = ^clong;
  3.      54   cslong                 = int64;              pcslong                = ^cslong;
  4.      55   culong                 = qword;              pculong                = ^culong;
  5.      56 {$else}
  6.      57   clong                  = longint;            pclong                 = ^clong;
  7.      58   cslong                 = longint;            pcslong                = ^cslong;
  8.      59   culong                 = cardinal;           pculong                = ^culong;
  9.      60 {$endif}
  10.  

Not to mince words, this isn't the first time I've seen this sort of thing.

But if you'd started off with the example program- and this is the third- sorry, FOURTH- time I've told you this- you wouldn't have been caught by that one or at least would have had a much better idea of where to look.

MarkMLl
« Last Edit: May 20, 2022, 10:43:09 am by MarkMLl »
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

 

TinyPortal © 2005-2018