MQGET big message ( > 4MB) from the queue results in error 2010 - c

I am trying to receive the message from the queue using ANSI-C and MQGET function. The problem is that I always get error 2010 (MQRC_DATA_LENGTH_ERROR).
I found out that this error concerns parameter 7 of the MQGET call (DataLength). The message on my queue has 7157460 bytes. The channel I am using for MQGET has the "Maximum message length" set to 104857600 (as well as the queue holding the message).
I am even using the MQGET from this example:
http://www.capitalware.biz/dl/code/c/msg2file.zip
And I still end up with error 2010. What am I doing wrong? Should I somehow increase the maximum size of the message in MQSERVER environment variable?
MQGET call:
/* ... */
MQLONG messlen; /* message length received */
MQGET(Hcon, /* connection handle */
Hobj, /* object handle */
&md, /* message descriptor */
&gmo, /* get message options */
buflen, /* pBuffer length */
pBuffer, /* pointer to message buffer */
&messlen, /* message length */
&CompCode, /* completion code */
&Reason); /* reason code */

I've got it! The answer is to use MQCONNX call to connect to queue manager.
Example:
#include <cmqxc.h>
/* ... */
MQCNO mqcno = {MQCNO_DEFAULT} ; /* Connection options */
MQCD mqcd = {MQCD_CLIENT_CONN_DEFAULT}; /* Channel Defs */
/* ... */
mqcd.MaxMsgLength = 104857600L; /* 100 MB */
MQCONNX(mQueueManager.Name,
&mqcno,
&mQueueManager.ConnectionHandle,
&mQueueManager.CompletionCode,
&mQueueManager.ReasonCode);
It worked like a charm!
But please remember - if you find yourself needing to increase the maximum message size - think twice. There is probably something wrong with the design. In another words - MQ should not be used for transferring big messages. MQ File Transfer Edition is one of the solutions then.

Related

I'm trying to receive UART interrupts

I want to receive UART interrupts, but shouldn't the basic structure of the interrupts be made like that?
Sometimes it doesn't work and sometimes it prints out printf ("test\r\n") but sometimes it doesn't print out the received data, but I don't know what the cause is Can you tell me the solution?
I tried to pull the HAL_UART_Receive_IT door out while, but it didn't work
I don't think it's a connection problem since I'm sending a message
void USART1_IRQHandler(void)
{
/* USER CODE BEGIN USART1_IRQn 0 */
/* USER CODE END USART1_IRQn 0 */
HAL_UART_IRQHandler(&huart1);
/* USER CODE BEGIN USART1_IRQn 1 */
/* USER CODE END USART1_IRQn 1 */
}
When I entered this code, there was an error
Error[Li006]: duplicate definitions for "USART1_IRQHandler";
The code below is the code that is currently experiencing a problem
uint8_t received_msg[10];
char check_msg[10];
//UART read
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){
if(huart -> Instance == USART1){
printf("test\r\n");
HAL_UART_Receive_IT(&huart1, (uint8_t*)received_msg, sizeof(received_msg));
}
}
/* USER CODE END 0 */
/**
* #brief The application entry point.
* #retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_I2C1_Init();
MX_TIM6_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
HAL_TIM_Base_Start_IT(&htim6);
calibrate(0.01, 4);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1) {
rcvStat = HAL_UART_Receive_IT(&huart1, received_msg, sizeof(received_msg));
if(rcvStat != HAL_OK){
printf("error\r\n");
}
sprintf(check_msg, "%s", (char*)received_msg);
printf("%s\r\n", check_msg);
printf("%d, %d\r\n", timer, flag);
HAL_Delay(timer);
printf("---------------------\r\n");
memset(received_msg, 0, strlen(received_msg));
memset(check_msg, 0, strlen(check_msg));
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
Call the RX interrupt once before the while loop and then after you have recieved the data in the ISR. Remove it from the inside of the while.
It seems like in the update loop you are re-issuing the RX_IT call, you should call this once and wait for data to arrive (ISR fires) and then re-issue at that point inside of ISR. Otherwise with a message size greater than one byte, you could re-issue the IT function after it recieved a few bytes and miss some bytes since it requests 10 bytes before the interrupt fires after being issued once.
Your ISR should primarily only be there for moving the RX'd data from one spot, to another for processing.
Printf is a pig and will most likely cause you to miss messages coming in if they are coming in real-time and not a one-off message.
A suggestion, would be to implement some type of circular FIFO queue in the ISR which stuffs the data in a FIFO buffer and that FIFO is accessed in your control loop for parsing, or action. That way, you are reciving each symbol and quickly exiting the interrupt and all data should be there for processing. I have had great success with this method in the past.

Can't use shm_open after receiving from message queue

I'm trying to implement a number of IPC methods in the same code using the following steps:
1 - Process1 opens a message queue and reads the message sent from Process2
2 - Process1 closes and unlinks the message queue
3 - Process1 writes something to a shared memory.
At step 3 any shm_open(), memset() or memcpy() system calls fail and Eclipse hangs in a new window that says "can't find a source file at ***" for whatever function I call.
When I disable the queue receive operation and just do the shared memory everything works fine.
So I'm suspecting that there is some unfinished business happening within the queue which is blocking any further calls from the process
Here is the problem in code: (just added the relevant part)
...
static int receiveFromQ(char *msgQName)
{
int msgQFD;
char buffer[33];
/* Create and open the communication message queue */
msgQFD = mq_open(msgQName, O_RDONLY | O_CREAT, 0660, NULL);
/* Read the message from the queue and store it in the reception buffer */
memset(buffer, 0, sizeof(buffer));
mq_receive(msgQFD, buffer, sizeof(buffer), NULL); // This is a blocking point until a message is received
/* Use the data received ... */
/* Close the queue */
mq_close(msgQFD);
/* Remove the message queue */
mq_unlink(msgQName);
return 1;
}
int main(void)
{
char *key = SM_KEY;
int shmFD;
/* Receive the data from the queue */
int ret = receiveFromQ(MSGQ_NAME);
/* Creates a shared memory object in a kernel space, with size = 0 */
shmFD = shm_open(key, O_CREAT | O_RDWR | O_TRUNC, 0660); //The software stops here!
...
}
Instead of creating the shared memory, the software hangs at the shm_open() and claims that the source for the shm_open is not found.
As mentioned by #Petesh, the problem was inside the /* use the data received */ part which I omitted from the code because I thought it is irrelevant! To clarify: in this part I made a mistake with the size of data copied using memcpy() which caused a buffer overflow. This did not show any error but somehow blocked further processing of the program.
Thank you all for the useful comments.
memset(buffer, 0, sizeof(buffer));
This will set buffer[0] = 0 because sizeof(buffer) = sizeof(char*) = 1.
Better idea are:
char buffer[33] = {0};
Or
#define BUFFER_LEN 33U
...
char buffer[BUFFER_LEN];
...
memset(buffer, 0, sizeof(char) * BUFFER_LEN);
Or
memset(buffer, 0, sizeof(buffer) / sizeof(buffer[0]);
sizeof(buffer) / sizeof(buffer[0] calculate size of fixed array (non pointers allocate using malloc). So result will be 33.

Serialize Netbios struct to send over TCP/IP in C, possible?

I have 2 machines talking to each other using NetBIOS via NetBEUI. I am in the process of replacing NETBEUI with TCP. I am looking for the easiest and fastest way to do it. There is NetBios over TCP/IP protocol available but for some reason it's not working... I could not figure out why. So now, I am thinking to serialize the NetBIOS struct and send it over to another machine using TCP and de-serialize there. The struct look like below. Will serialize approach work?
typedef struct _NCB {
UCHAR ncb_command; /* command code */
UCHAR ncb_retcode; /* return code */
UCHAR ncb_lsn; /* local session number */
UCHAR ncb_num; /* number of our network name */
PUCHAR ncb_buffer; /* address of message buffer */
WORD ncb_length; /* size of message buffer */
UCHAR ncb_callname[NCBNAMSZ]; /* blank-padded name of remote */
UCHAR ncb_name[NCBNAMSZ]; /* our blank-padded netname */
UCHAR ncb_rto; /* rcv timeout/retry count */
UCHAR ncb_sto; /* send timeout/sys timeout */
void (CALLBACK *ncb_post)( struct _NCB * );
UCHAR ncb_lana_num; /* lana (adapter) number */
UCHAR ncb_cmd_cplt; /* 0xff => commmand pending */
#ifdef _WIN64
UCHAR ncb_reserve[18]; /* reserved, used by BIOS */
#else
UCHAR ncb_reserve[10]; /* reserved, used by BIOS */
#endif
HANDLE ncb_event; /* HANDLE to Win32 event which */
/* will be set to the signalled */
/* state when an ASYNCH command */
/* completes */
} NCB, *PNCB;

Adding attribute to buffer description in PostgreSQL source, now has spinlock error?

I would like to add an attribute to the buffer description in the PostgreSQL source code, but when I try to initialize it I get an error of: PANIC: stuck spinlock (0x7fc1cddd0cd0) detected at freelist.c:206
The struct is described in buf_internals.h as:
typedef struct sbufdesc
{
BufferTag tag; /* ID of page contained in buffer */
BufFlags flags; /* see bit definitions above */
uint16 usage_count; /* usage counter for clock sweep code */
unsigned refcount; /* # of backends holding pins on buffer */
int wait_backend_pid; /* backend PID of pin-count waiter */
int buf_age; //<<<<<<<<<<< The age of the buffer
slock_t buf_hdr_lock; /* protects the above fields */
int buf_id; /* buffer's index number (from 0) */
int freeNext; /* link in freelist chain */
LWLockId io_in_progress_lock; /* to wait for I/O to complete */
LWLockId content_lock; /* to lock access to buffer contents */
} BufferDesc;
but it gets stuck at line 206 of freelist.c, which is just:
LockBufHdr(buf);
All I've added was an int to the struct and set it to zero in the same place all the other buffers are initialized. How could this cause a spinlock error?
It looks like running make clean first has corrected the issue.

OS X: Generate core dump without bringing down the process?

I know how to generate a core dump on OS X when a process crashes, but what I really need to do is attach to a process, generate a core dump, then resume that process (without killing it).
A long time ago (maybe a year and a half ago) I had C code that would do this... It used the OS X kernel libraries to connect to a process, read all of its thread states and memory, and write that into a Mach-O file on disk. This worked great (and it's exactly what I'm looking for), but now I can't seem to find that code for the life of me. I seem to recall that code was related somewhat to the OS X system internals book, but that's just a vague recollection.
Does anyone know the code I'm talking about and could point me at it? If not does anyone know a good way of doing this preferably with some example code?
Edit: Here is the answer.
Information: http://osxbook.com/book/bonus/chapter8/core/
Program that will do it for you: http://osxbook.com/book/bonus/chapter8/core/download/gcore-1.3.tar.gz
I believe you are looking for this information
Specifically:
/* UNIX Third Edition, circa early 1973 */
/* ken/sig.c */
core()
{
int s, *ip;
extern schar;
/* u is the user area */
u.u_error = 0; /* reset error code to "no error" */
u.u_dirp = "core"; /* file name to search for */
ip = namei(&schar, 1); /* do search; schar means it's a kernel string */
if (ip == NULL) { /* failed to find */
if (u.u_error) /* because of some error */
return(0); /* so bail out */
ip = maknode(0666); /* didn't exist; so create it */
}
if (!access(ip, IWRITE)) { /* check "write" permission; 0 means OK */
itrunc(ip); /* truncate the core file */
/* first we write the user area */
u.u_offset[0] = 0; /* offset for I/O */
u.u_offset[1] = 0; /* offset for I/O */
u.u_base = &u; /* base address for I/O (user area itself) */
u.u_count = USIZE*64; /* bytes remaining for I/O; USIZE=8 */
u.u_segflg = 1; /* specify kernel address space */
writei(ip); /* do the write */
/*
* u_procp points to the process structure
* p_size is the size of the process's swappable image (x 64 bytes) */
*/
s = u.u_procp->p_size - USIZE; /* compute size left to write */
/*
* This sets up software prototype segmentation registers to implement
* text(=0 here), data(=s here), and stack(=0 here) sizes specified.
*/
estabur(0, s, 0);
u.u_base = 0; /* base address for I/O (start of space) */
u.u_count = s*64; /* s is in units of 64 bytes, so adjust */
u.u_segflg = 0; /* specify user address space */
writei(ip); /* do the write */
}
iput(ip); /* decrement inode reference count */
return(u.u_error==0); /* done */
}

Resources