I have 2 processes:
producer: creates an Transaction object inside a shared memory then waiting for consumer to read the data. The waiting is done via a semaphore which is a member of Transaction
consumer: reads the Transaction object created by producer and tells producer the reading is done by posting semaphore in Transaction object.
Consumer is able to read the data from shared memory but it crashes when it tries to post semaphore.
What's wrong with this implementation?
//producer
#include <string>
#include <semaphore.h>
#include <cstddef>
#include <sys/mman.h>
#include <sys/stat.h> /* For mode constants */
#include <fcntl.h> /* For O_* constants */
#include <unistd.h>
#include <iostream>
constexpr char g_shared_mem_name[]="/our_shared_mem_new";
class Transaction
{
public:
virtual ~Transaction() = default;
Transaction(const uint32_t f_count) : m_count{f_count}{}
sem_t m_sem;
uint32_t m_count{0};
};
void* createSharedMem(const char *f_name, const size_t f_size) {
int fd = shm_open(f_name, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
if (fd != -1) {
// A new shared memory object initially has zero length.
// The size of the object can be set using ftruncate.
// The newly allocated bytes of a shared memory object are
// automatically initialized to 0
if (ftruncate(fd, f_size) == -1) {
return nullptr;
}
return mmap(NULL, f_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0 );
}
else {
return nullptr;
}
}
int main()
{
void * shared_mem = createSharedMem(g_shared_mem_name, sizeof(Transaction));
if ( shared_mem )
{
Transaction* shared_obj = new(shared_mem) Transaction(2022);
if( sem_init(&shared_obj->m_sem,1,0) == -1) {
std::cerr << "Unable to initialize m_sem_init\n";
}
//waiting for consumer to finish reading data
if( sem_wait(&shared_obj->m_sem) == -1) {
std::cerr << "Error on waiting for semaphore\n";
}
}
else {
std::cerr << "Unable to create shared object\n";
}
shm_unlink(g_shared_mem_name);
return EXIT_SUCCESS;
}
Consumer
#include <string>
#include <semaphore.h>
#include <cstddef>
#include <sys/mman.h>
#include <sys/stat.h> /* For mode constants */
#include <fcntl.h> /* For O_* constants */
#include <unistd.h>
#include <iostream>
constexpr char g_shared_mem_name[]="/our_shared_mem_new";
class Transaction
{
public:
virtual ~Transaction() = default;
Transaction(const uint32_t f_count) : m_count{f_count}{}
sem_t m_sem;
uint32_t m_count{0};
};
void* openSharedMem(const char * f_name, const size_t f_size) {
int fd = shm_open(f_name, O_RDONLY, 0);
if( fd != -1 ) {
return mmap(NULL, f_size, PROT_READ, MAP_SHARED, fd, 0 );
}
else {
return nullptr;
}
}
int main()
{
void* shared_mem = openSharedMem(g_shared_mem_name, sizeof(Transaction));
if (shared_mem) {
Transaction * m_inst = (Transaction*)shared_mem;
std::cout << "value of cnt:" << m_inst->m_count << std::endl;
//crash here
if (sem_post(&m_inst->m_sem) == -1) {
std::cerr << "Unable to post semaphore\n";
}
}
else {
std::cerr << "Unable to open shared object\n";
}
return EXIT_SUCCESS;
}
Output
value of cnt:2022
Segmentation fault (core dumped)
Related
I plan on rewriting this to assembly so I can't use c or c++ standard library. The code below runs perfectly. However I want a thread instead of a second process. If you uncomment /*CLONE_THREAD|*/ on line 25 waitpid will return -1. I would like to have a blocking function that will resume when my thread is complete. I couldn't figure out by looking at the man pages what it expects me to do
#include <sys/wait.h>
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
int globalValue=0;
static int childFunc(void*arg)
{
printf("Global value is %d\n", globalValue);
globalValue += *(int*)&arg;
return 31;
}
int main(int argc, char *argv[])
{
auto stack_size = 1024 * 1024;
auto stack = (char*)mmap(NULL, stack_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
if (stack == MAP_FAILED) { perror("mmap"); exit(EXIT_FAILURE); }
globalValue = 5;
auto pid = clone(childFunc, stack + stack_size, /*CLONE_THREAD|*/CLONE_VM|CLONE_SIGHAND|SIGCHLD, (void*)7);
sleep(1); //So main and child printf don't collide
if (pid == -1) { perror("clone"); exit(EXIT_FAILURE); }
printf("clone() returned %d\n", pid);
int status;
int waitVal = waitpid(-1, &status, __WALL);
printf("Expecting 12 got %d. Expecting 31 got %d. ID=%d\n", globalValue, WEXITSTATUS(status), waitVal);
return 0;
}
If you want to call functions asynchronously with threads I recommend using std::async. Example here :
#include <iostream>
#include <future>
#include <mutex>
#include <condition_variable>
int globalValue = 0; // could also have been std::atomic<int> but I choose a mutex (to also serialize output to std::cout)
std::mutex mtx; // to protect access to data in multithreaded applications you can use mutexes
int childFunc(const int value)
{
std::unique_lock<std::mutex> lock(mtx);
globalValue = value;
std::cout << "Global value set to " << globalValue << "\n";
return 31;
}
int getValue()
{
std::unique_lock<std::mutex> lock(mtx);
return globalValue;
}
int main(int argc, char* argv[])
{
// shared memory stuff is not needed for threads
// launch childFunc asynchronously
// using a lambda function : https://en.cppreference.com/w/cpp/language/lambda
// to call a function asynchronously : https://en.cppreference.com/w/cpp/thread/async
// note I didn't ues the C++ thread class, it can launch things asynchronously
// however async is both a better abstraction and you can return values (and exceptions)
// to the calling thread if you need to (which you do in this case)
std::future<int> future = std::async(std::launch::async, []
{
return childFunc(12);
});
// wait until asynchronous function call is complete
// and get its return value;
int value_from_async = future.get();
std::cout << "Expected global value 12, value = " << getValue() << "\n";
std::cout << "Expected return value from asynchronous process is 31, value = " << value_from_async << "\n";
return 0;
}
Recently I upgraded my OS from RHEL 7.6(gcc 4.8.5) to RHEL 8.4(gcc 8.4) and I'm facing issues related to process synchronization using pthread_mutex_t and pthread_cond_t. The reason I'm not using C++ std::mutex and std::condition_variable is because they doesn't support synchronization between processes. This used to work well in gcc 4.8.5 but not in gcc 8.4. This is my code
Binary_Semaphore.h
#ifndef BINARY_SEMAPHORE_H
#define BINARY_SEMAPHORE_H
#include <iostream>
#include <string>
#include <cstdlib>
#include <unistd.h>
#include <pthread.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <fcntl.h>
struct binary_semaphore_attr {
pthread_mutex_t mutex;
pthread_cond_t cvar;
bool flag;
};
class Binary_Semaphore {
struct binary_semaphore_attr *bin_sem_attr;
const std::string bin_sem_attr_shm_ID;
const bool is_process_shared;
const bool is_to_be_created;
public:
Binary_Semaphore(const std::string& bin_sem_attr_shm_ID, const bool is_process_shared, const bool is_to_be_created);
~Binary_Semaphore();
void post();
void wait();
template<typename T>
static void create_shared_memory(T **shm, const std::string& shm_ID, const bool is_to_be_created, const int o_flags, const int mode) {
int shm_fd;
if ((shm_fd = shm_open(shm_ID.c_str(), o_flags, mode)) == -1) {
std::cerr << "shm_open failed with " << shm_ID << "\n";
exit(EXIT_FAILURE);
}
if (is_to_be_created) {
if (ftruncate(shm_fd, sizeof(T)) == -1) {
std::cerr << "ftruncate failed with " << shm_ID << "\n";
exit(EXIT_FAILURE);
}
}
if ((*shm = reinterpret_cast<T*>(mmap(nullptr, sizeof(T), PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0))) == MAP_FAILED) {
std::cerr << "mmap failed with " << shm_ID << "\n";
exit(EXIT_FAILURE);
}
close(shm_fd);
}
};
#endif
Binary_Semaphore.cpp
#include "Binary_Semaphore.h"
Binary_Semaphore::Binary_Semaphore(const std::string& bin_sem_attr_shm_ID, const bool is_process_shared, const bool is_to_be_created) : bin_sem_attr_shm_ID(bin_sem_attr_shm_ID), is_process_shared(is_process_shared), is_to_be_created(is_to_be_created) {
/* set binary semaphore attribute */
if (is_to_be_created) {
if (is_process_shared) {
create_shared_memory(&bin_sem_attr, bin_sem_attr_shm_ID, is_to_be_created, O_CREAT | O_RDWR | O_TRUNC, S_IRWXU | S_IRWXG);
/* set mutex shared between processes */
pthread_mutexattr_t mutex_attr;
pthread_mutexattr_init(&mutex_attr);
pthread_mutexattr_setpshared(&mutex_attr, PTHREAD_PROCESS_SHARED);
pthread_mutexattr_setrobust(&mutex_attr, PTHREAD_MUTEX_ROBUST);
pthread_mutex_init(&bin_sem_attr->mutex, &mutex_attr);
pthread_mutexattr_destroy(&mutex_attr);
/* set cvar shared between processes */
pthread_condattr_t cvar_attr;
pthread_condattr_init(&cvar_attr);
pthread_condattr_setpshared(&cvar_attr, PTHREAD_PROCESS_SHARED);
pthread_cond_init(&bin_sem_attr->cvar, &cvar_attr);
pthread_condattr_destroy(&cvar_attr);
} else
bin_sem_attr = new binary_semaphore_attr();
} else {
if (is_process_shared)
create_shared_memory(&bin_sem_attr, bin_sem_attr_shm_ID, is_to_be_created, O_RDWR, S_IRUSR | S_IRGRP | S_IWUSR | S_IWGRP);
}
}
Binary_Semaphore::~Binary_Semaphore() {
if (is_to_be_created) {
pthread_mutex_destroy(&bin_sem_attr->mutex);
pthread_cond_destroy(&bin_sem_attr->cvar);
}
if (is_process_shared) {
munmap(bin_sem_attr, sizeof(binary_semaphore_attr));
shm_unlink(bin_sem_attr_shm_ID.c_str());
}
}
void Binary_Semaphore::post() {
if (pthread_mutex_lock(&bin_sem_attr->mutex) == EOWNERDEAD)
pthread_mutex_consistent(&bin_sem_attr->mutex);
bin_sem_attr->flag = true;
pthread_mutex_unlock(&bin_sem_attr->mutex);
pthread_cond_signal(&bin_sem_attr->cvar);
}
void Binary_Semaphore::wait() {
if (pthread_mutex_lock(&bin_sem_attr->mutex) == EOWNERDEAD)
pthread_mutex_consistent(&bin_sem_attr->mutex);
while (!bin_sem_attr->flag) {
if (pthread_cond_wait(&bin_sem_attr->cvar, &bin_sem_attr->mutex) == EOWNERDEAD)
pthread_mutex_consistent(&bin_sem_attr->mutex);
}
bin_sem_attr->flag = false;
pthread_mutex_unlock(&bin_sem_attr->mutex);
}
First_Process.cpp
#include <iostream>
#include <string>
#include <chrono>
#include <thread>
#include "Binary_Semaphore.h"
int main() {
static const std::string BSEM = R"(/BSEM)";
Binary_Semaphore *binary_sem = new Binary_Semaphore(BSEM, true, true);
while (true) {
binary_sem->post();
std::cout << "signal posted" << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1LL));
}
}
Second_Process.cpp
#include <iostream>
#include <string>
#include "Binary_Semaphore.h"
int main() {
static const std::string BSEM = R"(/BSEM)";
Binary_Semaphore *binary_sem = new Binary_Semaphore(BSEM, true, false);
while (true) {
binary_sem->wait();
std::cout << "signal received" << std::endl;
}
}
Run first process followed by second process and then abruptly terminate second process using Ctrl^C and then rerun second process, no more prints on the terminal(both first process and second process).
Did anybody face same kind of issue with latest gcc versions?
glibc does not support robust condition variables. (They are not part of POSIX.) You need to re-create the shared memory segment with the condition variables if one of the participating processes terminates abnormally.
Using C++11 on Linux kernel 4.4.0-57, I'm trying to run two busy-looping processes (say p1, p2) pinned (pthread_setaffinity_np) on the same core and making sure the interleaving execution order by using POSIX semaphore (semaphore.h) and sched_yield(). But it did not work out well.
Below is the parent code (parent-task) that spawns 2 processes and each executes child-task code.
#include <stdio.h>
#include <cstdlib>
#include <errno.h> // errno
#include <iostream> // cout cerr
#include <semaphore.h> // semaphore
#include <fcntl.h> // O_CREAT
#include <unistd.h> // fork
#include <string.h> // cpp string
#include <sys/types.h> //
#include <sys/wait.h> // wait()
int init_semaphore(){
std::string sname = "/SEM_CORE";
sem_t* sem = sem_open ( sname.c_str(), O_CREAT, 0644, 1 );
if ( sem == SEM_FAILED ) {
std::cerr << "sem_open failed!\n";
return -1;
}
sem_init( sem, 0, 1 );
return 0;
}
// Fork and exec child-task.
// Return pid of child
int fork_and_exec( std::string pname, char* cpuid ){
int pid = fork();
if ( pid == 0) {
// Child
char* const params[] = { "./child-task", "99", strdup( pname.c_str() ), cpuid, NULL };
execv( params[0], params );
exit(0);
}
else {
// Parent
return pid;
}
}
int main( int argc, char* argv[] ) {
if ( argc <= 1 )
printf( "Usage ./parent-task <cpuid> \n" );
char* cpuid = argv[1];
std::string pnames[2] = { "p111", "p222" };
init_semaphore();
int childid[ 2 ] = { 0 };
int i = 0;
for( std::string pname : pnames ){
childid[ i ] = fork_and_exec( pname, cpuid );
}
for ( i=0; i<2; i++ )
if ( waitpid( childid[i], NULL, 0 ) < 0 )
perror( "waitpid() failed.\n" );
return 0;
}
The child-task code looks like this:
#include <cstdlib>
#include <stdio.h>
#include <sched.h>
#include <pthread.h>
#include <stdint.h>
#include <errno.h>
#include <semaphore.h>
#include <iostream>
#include <sys/types.h>
#include <fcntl.h> // O_CREAT
sem_t* sm;
int set_cpu_affinity( int cpuid ) {
pthread_t current_thread = pthread_self();
cpu_set_t cpuset;
CPU_ZERO( &cpuset );
CPU_SET( cpuid, &cpuset );
return pthread_setaffinity_np( current_thread,
sizeof( cpu_set_t ), &cpuset );
}
int lookup_semaphore() {
sm = sem_open( "/SEM_CORE", O_RDWR );
if ( sm == SEM_FAILED ) {
std::cerr << "sem_open failed!" << std::endl ;
return -1;
}
}
int main( int argc, char* argv[] ) {
printf( "Usage: ./child-task <PRIORITY> <PROCESS-NAME> <CPUID>\n" );
printf( "Setting SCHED_RR and priority to %d\n", atoi( argv[1] ) );
set_cpu_affinity( atoi( argv[3] ) );
lookup_semaphore();
int res;
uint32_t n = 0;
while ( 1 ) {
n += 1;
if ( !( n % 1000 ) ) {
res = sem_wait( sm );
if( res != 0 ) {
printf(" sem_wait %s. errno: %d\n", argv[2], errno);
}
printf( "Inst:%s RR Prio %s running (n=%u)\n", argv[2], argv[1], n );
fflush( stdout );
sem_post( sm );
sched_yield();
}
sched_yield();
}
sem_close( sm );
}
In the child-task code, I have if ( !( n % 1000 ) ) to experiment reducing the contention/load in waiting and posting the semaphore. The outcome I got is that when n % 1000, one of the child process will be always in Sleep state (from top) and the other child process executes properly. However, if I set n % 10000, i.e. less load/contention, both processes will run and printout the output interleavingly which is my expected outcome.
Does anyone know if this is the limitaion of semaphore.h or there's a better way to ensure processes execution order?
Updated: I did a simple example with threads and semaphore, note that sched_yield may help avoiding unnecessary wakeups of the thread that is not 'in turn' to do work, but yielding is not a guarantee. I also show an example with mutex/condvar that is guaranteed to work, no yield necessary.
#include <stdexcept>
#include <semaphore.h>
#include <pthread.h>
#include <thread>
#include <iostream>
using std::thread;
using std::cout;
sem_t sem;
int count = 0;
const int NR_WORK_ITEMS = 10;
void do_work(int worker_id)
{
cout << "Worker " << worker_id << '\n';
}
void foo(int work_on_odd)
{
int result;
int contention_count = 0;
while (count < NR_WORK_ITEMS)
{
result = sem_wait(&sem);
if (result) {
throw std::runtime_error("sem_wait failed!");
}
if (count % 2 == work_on_odd)
{
do_work(work_on_odd);
count++;
}
else
{
contention_count++;
}
result = sem_post(&sem);
if (result) {
throw std::runtime_error("sem_post failed!");
}
result = sched_yield();
if (result < 0) {
throw std::runtime_error("yield failed!");
}
}
cout << "Worker " << work_on_odd << " terminating. Nr of redundant wakeups from sem_wait: " <<
contention_count << '\n';
}
int main()
{
int result = sem_init(&sem, 0, 1);
if (result) {
throw std::runtime_error("sem_init failed!");
}
thread t0 = thread(foo, 0);
thread t1 = thread(foo, 1);
t0.join();
t1.join();
return 0;
}
Here is one way to do it with condition variables and mutexes. Translating from C++ std threads to pthreads should be trivial. To do it between processes, you would have to use a pthread mutex type that can be shared between processes. Maybe the condvar and the mutex can both be placed in shared memory, to achieve the same thing I do below with threads.
See also the manpage pthread_condattr_setpshared (3) or
http://manpages.ubuntu.com/manpages/wily/man3/pthread_condattr_setpshared.3posix.html
On the other hand, maybe it is simpler to just use a SOCK_STREAM unix domain socket between the two worker processes, and just block on the socket until the peer worker pings you (i.e. send one char) over the socket.
#include <cassert>
#include <iostream>
#include <thread>
#include <condition_variable>
#include <unistd.h>
using std::thread;
using std::condition_variable;
using std::mutex;
using std::unique_lock;
using std::cout;
condition_variable cv;
mutex mtx;
int count;
void dowork(int arg)
{
std::thread::id this_id = std::this_thread::get_id();
cout << "Arg: " << arg << ", thread id: " << this_id << '\n';
}
void tfunc(int work_on_odd)
{
assert(work_on_odd < 2);
auto check_can_work = [&count, &work_on_odd](){ return ((count % 2) ==
work_on_odd); };
while (count < 10)
{
unique_lock<mutex> lk(mtx);
cv.wait (lk, check_can_work);
dowork(work_on_odd);
count++;
cv.notify_one();
// Lock is unlocked automatically here, but with threads and condvars,
// it is actually better to unlock manually before notify_one.
}
}
int main()
{
count = 0;
thread t0 = thread(tfunc, 0);
thread t1 = thread(tfunc, 1);
sleep(1);
cv.notify_one();
t0.join();
t1.join();
}
I have two programs and I want them to communicate together by msgrcv() && msgsnd(). I so have a master program which init the message queue and start the 2 others programs:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string>
#include <iostream>
#include <unistd.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <stdio.h>
int main() {
int qid = msgget(ftok(".",'u'), 0);
char* params[3];
params[1] = (char *)malloc(sizeof(char) * 9);
sprintf(params[1], "%d", qid);
params[2] = NULL;
printf("qid = %d and qid(str) = %s", qid, params[1]);
// return (0);
//spawning two child processes
pid_t cpid = fork();
if (cpid == 0) {
params[0] = (char*)"./sender";
execv(params[0], params);
exit(0);
}
cpid = fork();
if (cpid == 0) {
params[0] = (char*)"./receiver";
execv(params[0], params);
exit(0);
}
while (wait(NULL) != -1); // waiting for both children to terminate
msgctl(qid, IPC_RMID, NULL);
std::cout << "parent proc: " << getpid()
<< " now exits" << std::endl;
exit(0);
}
I also prepare the parameters and start the both following programs:
sender
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#include <iostream>
#include <unistd.h>
#include <sys/wait.h>
#include <stdlib.h>
int main(int ac, char **av) {
if (ac != 2)
return (-1);
// create my msgQ with key value from ftok()
// int qid = msgget(IPC_PRIVATE, IPC_EXCL|IPC_CREAT|0600);
int qid = atoi(av[1]);
// declare my message buffer
struct buf {
long mtype; // required
char greeting[50]; // mesg content
};
buf msg;
int size = sizeof(msg)-sizeof(long);
std::cout << "Welcome in the prog assignment 2! Type [exit] to stop the program." << std::endl;
bool exit = false;
while (!exit)
{
std::cout << getpid() << ": ";
std::cin.getline(msg.greeting, 50, '\n');
std::cout << msg.greeting << std::endl;
msg.mtype = 114; // only reading mesg with type mtype = 114
if (strcmp(msg.greeting, "exit") == 0)
exit = true;
msgsnd(qid, (struct msgbuf *)&msg, size, 0);
}
}
receiver
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#include <iostream>
#include <unistd.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <stdio.h>
int main(int ac, char **av) {
int i = 0;
while (i < ac)
printf("AV: %s\n", av[i++]);
if (ac != 2)
return (-1);
// int qid = msgget(IPC_PRIVATE, IPC_EXCL|IPC_CREAT|0600);
int qid = atoi(av[1]);
// declare my message buffer
struct buf {
long mtype;
char greeting[50];
};
buf msg;
int size = sizeof(msg)-sizeof(long);
bool exit = false;
while (!exit)
{
msgrcv(qid, (struct msgbuf *)&msg, size, 114, 0);
if (strcmp(msg.greeting, "exit") == 0)
exit = true;
std::cout << getpid() << msg.greeting << std::endl;
}
std::cout << "get out" << std::endl;
}
It doesn't work and I'm not sure to understand why because, I'm creating the message queue, passing it as parameter, then I put it back as int and then use it. However, it just gives me an infinite loop of weird display, why?
ANy help is welcome.. Thank !
I am trying to make a tutorial for my students on Shared Memory. However, I see a crash while waiting or posting a semaphore. I am using sem_open API to initialize the semaphore. Do I need to allocate some memory before doing sem_open? It looks to me a segmentation fault. Can you please help me on it?
#include <iostream>
#include <sys/ipc.h>
#include <sys/stat.h>
#include <sys/shm.h>
#include <string.h>
/** page size **/
#include <unistd.h>
/** memcpy **/
#include <stdio.h>
#include <semaphore.h>
#include <fcntl.h>
using namespace std;
class READER_WRITER_A
{
private:
string msg;
void *shm_ptr;
int shm_id;
sem_t *sem_rw;
void Init_Shm();
void Init_Sem();
public:
void Read_Msg();
void Write_Msg(string s1);
READER_WRITER_A();
};
void READER_WRITER_A::Init_Shm()
{
key_t key;
key = ftok("/home/joshis1/Downloads/IPC-BLOG/shm",1);
shm_id = shmget(key, getpagesize(), IPC_CREAT| 0660);
shm_ptr = shmat(shm_id, NULL, 0660);
}
void READER_WRITER_A::Init_Sem()
{
sem_rw = sem_open("/home/joshis1/Downloads/IPC-BLOG/rw_sem", O_RDWR | O_CREAT, 0666, 0);
cout<<"Sem_Post calling"<<endl;
if( sem_rw < 0 )
cout<<"Error in opening the sem_rw"<<endl;
sem_post(sem_rw);
cout<<"Sem_Post done"<<endl;
}
void READER_WRITER_A::Read_Msg()
{
//sem_wait(sem_rw);
int *size = (int *)shm_ptr;
void *msg_ptr = shm_ptr;
msg_ptr+=sizeof(int);
cout<<"Message size is = "<<*size<<endl;
memcpy(&msg,(string *)msg_ptr,*size);
cout<<"Reading Message-- "<<msg<<endl;
//sem_post(sem_rw);
}
void READER_WRITER_A::Write_Msg(string s1)
{
//sem_wait(sem_rw);
void *msg_ptr = shm_ptr;
msg = s1;
int *pt = (int*)shm_ptr;
*pt = s1.size();
cout<<"Writing Message size = "<<*pt<<endl;
msg_ptr+=sizeof(int);
cout<<"Writing Message-- "<<s1<<endl;
memcpy((string *)msg_ptr,&msg,s1.size());
//sem_post(sem_rw);
}
READER_WRITER_A::READER_WRITER_A()
{
Init_Shm();
Init_Sem();
}
int main( int argc, char *argv[])
{
READER_WRITER_A val;
val.Write_Msg("I am A-RW");
val.Read_Msg();
return 0;
}
Here is the output.
$ ./reader_writer_a.out
Sem_Post calling
Segmentation fault (core dumped)
Analyzing coredump here.
(gdb) bt
#0 0x0000003fb060d790 in sem_post () from /lib64/libpthread.so.0
#1 0x0000000000400fd0 in READER_WRITER_A::Init_Sem (this=0x7fff50e322a0) at reader_writer_a.cpp:52
#2 0x0000000000401199 in READER_WRITER_A::READER_WRITER_A (this=0x7fff50e322a0) at reader_writer_a.cpp:86
#3 0x00000000004011d8 in main (argc=1, argv=0x7fff50e323c8) at reader_writer_a.cpp:92
void READER_WRITER_A::Init_Sem()
{
sem_rw = sem_open("/home/joshis1/Downloads/IPC-BLOG/rw_sem", O_RDWR | O_CREAT, 0666, 0);
cout<<"Sem_Post calling"<<endl;
if( sem_rw < 0 )
cout<<"Error in opening the sem_rw"<<endl;
sem_post(sem_rw);
cout<<"Sem_Post done"<<endl;
}
sem_open() returns SEM_FAILED on failure and otherwise it's an address. It doesn't make sense to check it against 0.
If it failed, your sem_post() call might crash the program