Following application program executes successfully on Ubuntu 16.04.
But a HANG condition is observed on Ubuntu 18.04, and Ubuntu 20.04.
The application program contains two parts Sender and Receiver.
Below are the steps to reproduce the problem.
- Execute the "Sender" application program with command "./Sender_Receiver Sender Init" on new terminal
- Observe prints on the terminal after every 5 seconds to confirm that Sender application is sending the signal
- Execute the "Receiver" application program with command "./Sender_Receiver Receiver" on new terminal
- Observe prints on the terminal after every 5 seconds to confirm that Receiver application is receiving the signal
- Terminate the "Receiver" application using (ctrl + c). This will terminate the Receiver application.
- Observe prints on the Sender terminal after every 5 seconds to confirm that Sender application still sending the signal and running
- Again Execute the "Receiver" application program with command "./Sender_Receiver Receiver" on terminal
- Observe prints on the Sender and Receiver terminals, The "Sender" and "Receiver" application will be observed in the HANG condition on Ubuntu 18.04, and Ubuntu 20.04.
Note:- For the same steps, the application program works normally when executed on Ubuntu 16.04.
Command used to build the code: gcc -g -Wall Sender_Receiver.cpp -o Sender_Receiver -L /lib -lrt -lpthread
Command used to execute Sender application: ./Sender_Receiver Sender Init
Command used to execute Receiver application: ./Sender_Receiver Receiver
Can any one suggest the reason for the HANG condition on Ubuntu 18.04, and Ubuntu 20.04 with the probable solution.
Code in the Sender_Receiver.cpp as below,
Code:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <time.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include <cerrno>
#include <sys/time.h>
#include <limits.h>
#define SHM_DIR_PATH "/dev/shm/"
#define ERROR -1
/* share memory access using MMAP */
void mmap_wrapper(void** vppPtr, unsigned int uiMemorySize, char* cpMemoryName)
{
int iFdShm = ERROR;
char cShmPath[NAME_MAX] = { 0 };
int iRet = ERROR;
void* vpMmapPtr = NULL;
/* Sanity Check for pointer*/
if(vppPtr == NULL)
{
printf("\nvppPtr Error");
}
/* Sanity Check memory size*/
if(uiMemorySize < 1)
{
printf("\nuiMemorySize Error");
}
/* Sanity Check memory name pointer*/
if(cpMemoryName == NULL)
{
printf("\ncpMemoryName Error");
}
/* Sanity Check memory name string size */
if( (strlen(cpMemoryName) + strlen(SHM_DIR_PATH)) >= NAME_MAX)
{
printf("\ncpMemoryName Error");
}
/* Open share memory object */
iFdShm = shm_open(cpMemoryName, O_CREAT | O_RDWR, ACCESSPERMS);
if(iFdShm == ERROR)
{
printf("\nError during shm_open()");
printf("\nError:%d: %s",errno, strerror(errno));
}
/* Create file name with particular path SHM_DIR_PATH*/
strcpy(cShmPath, SHM_DIR_PATH);
strcat(cShmPath, cpMemoryName);
/* Change permission of the file*/
iRet = chmod(cShmPath, ACCESSPERMS);
if(iRet == ERROR)
{
printf("\nError during chmod()");
printf("\nError:%d: %s",errno, strerror(errno));
}
/* truncate the file as per the required memory size */
iRet = ftruncate(iFdShm, uiMemorySize);
if(iRet == ERROR)
{
printf("\nError during ftruncate()");
printf("\nError:%d: %s",errno, strerror(errno));
}
/* map the shared memory in the processes address space*/
vpMmapPtr = mmap(0, uiMemorySize, PROT_WRITE, MAP_SHARED, iFdShm, 0);
if(vpMmapPtr == MAP_FAILED)
{
printf("\nError during mmap()");
printf("\nError:%d: %s",errno, strerror(errno));
}
/* close the file */
iRet = close(iFdShm);
if(iRet == ERROR)
{
printf("\nError during close()");
printf("\nError:%d: %s",errno, strerror(errno));
}
/* return the shared memory pointer */
(*vppPtr) = vpMmapPtr;
}
int main(int argc, char *argv[])
{
printf("\nExecuting_main");
if( argc == 3 )
{
printf("\nThe argument supplied is %s\t%s\n", argv[1],argv[2]);
}
else if( argc == 2 )
{
printf("\nThe argument supplied is %s\n", argv[1]);
}
else if( argc > 3 )
{
printf("\nToo many arguments supplied.\n");
}
else
{
printf("\nOne argument expected.\n");
}
/* condition variable shared between Sender process and Receiver process */
pthread_cond_t *shmVar;
mmap_wrapper((void**)&shmVar, sizeof(pthread_cond_t),(char*)"shmVar");
/* mutex shared between Sender process and Receiver process */
pthread_mutex_t *shmVarMutex;
mmap_wrapper((void**)&shmVarMutex, sizeof(pthread_mutex_t),(char*)"shmVarMutex");
if(( argc == 3 ) && (strcmp(argv[2],"Init") == 0))
{
printf("\n%s::Init",argv[2]);
pthread_condattr_t attr;
pthread_condattr_init(&attr);
pthread_condattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
pthread_cond_init(shmVar, &attr);
pthread_mutexattr_t attr1;
pthread_mutexattr_init(&attr1);
pthread_mutexattr_setpshared(&attr1, PTHREAD_PROCESS_SHARED);
pthread_mutex_init(shmVarMutex, &attr1);
}
if(strcmp(argv[1],"Sender") == 0)
{
printf("\nSender::LoopStarting");
while(1)
{
sleep(5);
printf("\nSender::Locking");
pthread_mutex_lock(shmVarMutex);
printf("\nSender::Locked");
printf("\nSender::Sending");
pthread_cond_signal(shmVar);
printf("\nSender::Sent");
printf("\nSender::Unlocking");
pthread_mutex_unlock(shmVarMutex);
printf("\nSender::Unlocked");
}
}
else if(strcmp(argv[1],"Receiver") == 0)
{
int iRet = ERROR;
printf("\nReceiver::LoopStarting");
while(1)
{
printf("\nReceiver::Locking");
pthread_mutex_lock(shmVarMutex);
printf("\nReceiver::Locked");
printf("\nReceiver::Waiting");
if((iRet = pthread_cond_wait(shmVar, shmVarMutex)) == 0)
{
printf("\nReceiver::Received");
}
printf("\nReceiver::Unlocking");
pthread_mutex_unlock(shmVarMutex);
printf("\nReceiver::Unlocked");
}
}
printf("\nExiting_main");
}
Bookmarks