After calling msgrcv(), I got a E2BIG: on SunOS, CPP compiler.
Output is as following:
arguments:
MsgID: 335006
pointer: 0xffbfbac8
sizeof: 1040
MsgType: 0
MsgFlag: 2048
RetVal=-1
RM: message waiting failed with error 7.
In manual:
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
Maunal says for msgrcv(), E2BIG is got when “message text length is greater than msgsz and MSG_NOERROR isn’t specified in msgflg.”
But in my case, it looks liks the length is equal to msg text. By the way, how this function get the length of void *msgp? It is a void.
Sorry, I posted a long piece of codes since I am afraid to miss something.
Thanks.
EDIT:
Manual says,
The msgp argument is a pointer to caller-defined structure of the fol-
lowing general form:
struct msgbuf {
long mtype; /* message type, must be > 0 */
char mtext[1]; /* message data */
};
The mtext field is an array (or other structure) whose size is specified by msgsz, a non-negative integer value
I add more information by gdb as following:
227 RetVal = msgrcv( TDM_M[MyModule].msg_id,
228 (void *)&SysMsg,
229 (size_t)sizeof(T_MSGBUF),
230 MsgType,
231 MsgFlag);
23
235 */
(gdb) p sizeof(SysMsg)
$10 = 1044
(gdb) p sizeof(T_MSGBUF)
$11 = 1040
Length – Destination’s size = 4 (= size of long int), looks like it is correct.
In addition, I found the problem only happens to SunOS. The same code works fine on Linux.
Edit I found the root cause. Like the errno E2BIG indicating MsgLength is less than the message received, my send macro count a wrong value which was supposed to be equal to the MsgLength in WAIT_MSG().
Thank you for your advice and answers.
.h file
/* MSGBUF is defined for specific message
* SysMsg is defined as arg for msgrcv
*/
#define MSGBUF_SIZE 1040
#define MSGBODY_SIZE (MSGBUF_SIZE)
#define MSGBODY_SIZE1 (MSGBUF_SIZE-16)
typedef struct {
unsigned char SrcModule;
unsigned char DstModule;
unsigned char MsgType;
unsigned short SubMsgId;
unsigned short Length;
long int reserved;
} MsgHeader;
typedef struct _MsgBody {
unsigned char Data[MSGBODY_SIZE1];
} MSGBODY;
typedef struct _MsgBuf {
MsgHeader Header; // the header of message.
MSGBODY Body; // the message body.
} MSGBUF;
typedef struct _MsgInside {
long int MsgType;
MSGBUF MsgText;
} SYS_MSG;
.cpp
int WaitMsg (DMMODULE MyModule,
MSGBUF* pMsgBuf,
long MsgType,
int MsgFlag,
TIME_USEC abs_timeout)
{
SYS_MSG SysMsg;
int RetVal;
...
memset(&SysMsg, 0, sizeof(SYS_MSG));
printf("arguments:\n");
printf("MsgID: %d\n", Module[MyModule].msg_id);
printf("pointer: 0x%x\n", (void *)&SysMsg);
printf("sizeof: %d\n", (size_t)sizeof(T_MSGBUF));
printf("MsgType: %d\n", MsgType);
printf("MsgFlag: %d\n", MsgFlag);
/* Module is a global array in which msg_id is storing */
RetVal = msgrcv( Module [MyModule].msg_id,
(void *)&SysMsg,
(size_t)sizeof(MSGBUF),
MsgType,
MsgFlag);
/* So far, only ENOMSG is handled, the rest is ignored,
* Maybe a signal handler is needed later.
*/
if( RetVal == -1 )
{
switch (errno)
{
case ENOMSG:
return My_ENOMSG;
case E2BIG:
case EACCES:
case EAGAIN:
case EFAULT:
case EIDRM:
case EINTR:
case EINVAL:
/* Here is where the error reported */
printf("%s: message waiting failed with error %d.\n",
Module[MyModule].name, errno);
printf("%s: \n", strerror(errno));
return FAIL;
default:
printf("%s: message waiting failed with error %d.\n",
Module[MyModule].name, errno);
printf("%s: \n", strerror(errno));
return FAIL;
}
}
memcpy(pMsgBuf, &(SysMsg.MsgText), sizeof(T_MSGBUF));
printf("message is received by %s.\n", Module[MyModule].name);
return SUCC;
}
...
#define WAIT_MSG(MyModule,pMsgBuf,time_us ) \
WaitMsg((MyModule),(pMsgBuf),0,IPC_NOWAIT,0)
int main()
{
int rc = -1;
MSGBUF msgbuf;
rc = WAIT_MSG( RM, &msgbuf, 0 );
...
}
}
The error
E2BIGindicates that the message you are trying to receive doesn’t fit in your buffer. You have to make the buffer bigger. Your buffer is around 1020 or 1024 bytes, I’m not sure. If the incoming message is bigger, you getE2BIG.It seems like you are a little unclear on how pointers work. Pointers just point to a single location in memory, they don’t have lengths. (Even non-void pointers don’t have a “length”.) Whenever you specify a region of memory, you have to specify both its starting location (
void *) and its length (size_t). When you pass a range of memory to a function in C, the length is typically specified in one of three ways:setjmp, you pass a pointer to a region of memory which issizeof(jmp_buf)bytes long.fwriteormsgrcv.strlen.Advice:
void *, don’t use a cast; this can hide a bug in your code if you accidentally cast a non-pointer tovoid *. Pointers are automatically cast tovoid *when necessary.sizeofis alwayssize_t, don’t cast it. It’s like writing(int)1,(double)0.5, or(const char [6])"Hello".Don’t use
sizeof(type)formemcpyormsgrcvarguments. Typos inmemcpyarguments are a common source of errors, and referring to distant types makes them harder to spot when reading code.If you want your messages to be 1024 bytes, write that in the code. Don’t assemble a structure that just happens to add up to 1024 bytes, make it happen explicitly.