Parth Thakkar
Parth Thakkar

Reputation: 5475

Shared Memory program behaving weirdly

I've written the following code to make 2 processes chat using shared memory. But I'm facing some weird problems.

Let's say you send a message from process A, it gets displayed on process B's stdout and you can keep sending messages from process A without any problem. But as soon as you try to send a message from process B, everything stops working. No message is displayed on A. If you now try to send something from A, even that doesn't work. Even worse, if I start a new process, the second process generates a lot of garbage output at first, and then becomes dysfunctional - no further output gets displayed. I don't really understand what's going on.

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>

struct message {
    int senderid;
    char msg[100];
};
struct message_q {
    int write_ptr;
    int writing;
    struct message msgbuffer[100];
} *pmsgq;

key_t key;
int shmid;

int lastRead = -1;
void handleRead() {
    while(1) {
        while(lastRead+1 != pmsgq->write_ptr) {
            // don't display our own messages
            if(pmsgq->msgbuffer[1+lastRead].senderid != getppid())
                printf("Remote: %s\n",pmsgq->msgbuffer[++lastRead].msg);
        }
    }
}

void handleWrite() {
    char msg[100];
    while(1) {
        scanf("%s", msg);
        while(pmsgq->writing) 
            ;
        pmsgq->writing = 1;
        strcpy(pmsgq->msgbuffer[pmsgq->write_ptr].msg, msg);
        pmsgq->msgbuffer[pmsgq->write_ptr].senderid = getpid();
        pmsgq->write_ptr++;
        pmsgq->writing = 0;
    }
}

int main() {
    key = ftok("shared_mem_chat.c",'b');
    shmid = shmget(key, sizeof(struct message_q), IPC_CREAT | 0666);
    pmsgq = (struct message_q*) shmat(shmid, NULL, 0);
    pmsgq->write_ptr = 0;
    pmsgq->writing = 0;

    if(fork() == 0) {
        handleRead();
    }
    else {
        handleWrite();
    }
    return 0;
}

The reason to split Read and Write in two separate processes is to enable "live" chatting - otherwise scanf will block the execution till something is entered.

And I've also added a simple locking mechanism - I know that the write code here isn't really atomic, but I added it just for, let's say, simulating locking.

Upvotes: 0

Views: 137

Answers (1)

cleblanc
cleblanc

Reputation: 3688

I think you need to make lastRead a volatile. It seems to me like one process is caching that value and not getting the update from the other process. Just declare it like this

volatile int lastRead = -1;

Upvotes: 1

Related Questions