Hi guys,

I have been trying to implement a shared circular queue between 2 processes. My structures are as follows:

typedef struct client_entry {
	long shmid;
	int pid;
	struct client_entry *next;
	struct client_entry *prev;
} client_entry_t;

typedef struct client_queue {
	unsigned int num_entries; 
	long current_shmid;
	int notify;
	struct client_entry *first;
	struct client_entry *last;
	pthread_mutex_t region_mutex;
} client_queue_t;

This is shared between a server and a client. Server creates the shared memory (client queue), attaches it and waits for "notify" to be set.

A client process creates and attaches the shared memory (with same KEY as that of server), adds a new client (client_entry) to the queue and sets notify = 1.

On this, the server tries to access the newly created client_entry and tries to print entry->shmid.

Snippet of server

// loads shared memory at (client_queue_t *)shm
while(shm->notify != 1) {
		printf("\nWaiting... %d", shm->notify);
		sleep(1);
	}
        printf("\nGot Notification");
	pthread_mutex_lock(&shm->region_mutex);
	shm->notify = 0;
	pthread_mutex_unlock(&shm->region_mutex);

     printf("\nServer finds first SHMID as %ld", shm->first->shmid);

Snippet of client

// loads shm and creates a new_client_id
        client_entry_t client;
	client.shmid = new_client_id;
	client.pid = 1;

	pthread_mutex_lock(&shm->region_mutex);
	add_to_client(shm, &client);
	pthread_mutex_unlock(&shm->region_mutex);
thread_mutex_lock(&shm->region_mutex);
	//shm->num_entries = 0;
	shm->notify = 1;
	pthread_mutex_unlock(&shm->region_mutex);

       printf("\nClient finds SHMID as %ld", shm->first->shmid );

Functions used

extern void init_client(client_queue_t *client)
{

	client->first = NULL;
	client->last = NULL;

	client->num_entries = 0;

	fprintf(stderr, "\nClient queue initialized");
	return;
}

extern void add_to_client(client_queue_t *client, client_entry_t *entry)
{
        entry->next = NULL;
        entry->prev = client->last;

        if (client->first == NULL)
            client->first = entry;
        else
            client->last->next = entry;

        client->last = entry;

	printf("\nAdded to client queue: FIRST at %d", client->first->shmid);
    client->num_entries++;

	return;
}

Now, the add_to_client function gives the correct output
Server throws a segmentation fault
Client prints a different value.

I'm totally confused and stuck here. Please help me. Thanks.

> init_client()
Why doesn't this initialise the mutex (and everything else, especially notify)

> add_to_client()
It's probably safer if you use the mutex to guard this as well.

Adding you might get away with, but when it comes to removing things from the list, you definitely need to lock it.

> while(shm->notify != 1)
notify should probably be declared volatile.
If the compiler can't see it being changed in the loop, it might load shm->notify only once (in which case, your loop becomes infinite).

> client_entry_t client;
Lemme guess, this is a local variable.
You add a pointer to your local variable.
Code goes out of scope, local variable vanishes (and accumulates junk)
Server follows junk pointers and buys the farm.

Snippet of client

// loads shm and creates a new_client_id
        client_entry_t client;
	client.shmid = new_client_id;
	client.pid = 1;

	pthread_mutex_lock(&shm->region_mutex);
	add_to_client(shm, &client);
	pthread_mutex_unlock(&shm->region_mutex);
thread_mutex_lock(&shm->region_mutex);
	//shm->num_entries = 0;
	shm->notify = 1;
	pthread_mutex_unlock(&shm->region_mutex);

       printf("\nClient finds SHMID as %ld", shm->first->shmid );

Can you expand a client snippet? I don't quite understand what client_entry_t client; actually is. Is it local var on some procedure? Is it itself shared? If so, how it is attached to the server address space?

Besides that, I am not sure that you may use pthread methods in this context.

Edited 6 Years Ago by nezachem: n/a

> init_client()
Why doesn't this initialise the mutex (and everything else, especially notify)

> add_to_client()
It's probably safer if you use the mutex to guard this as well.

Yes. Right now mutex is not a concern, as I am not able to add just one entry and retrive it.

Adding you might get away with, but when it comes to removing things from the list, you definitely need to lock it.

> while(shm->notify != 1)
notify should probably be declared volatile.
If the compiler can't see it being changed in the loop, it might load shm->notify only once (in which case, your loop becomes infinite).

Hmm... I'll try that. Anyways, Server is able to check for its value to be 1 and exit the loop

> client_entry_t client;
Lemme guess, this is a local variable.
You add a pointer to your local variable.
Code goes out of scope, local variable vanishes (and accumulates junk)
Server follows junk pointers and buys the farm.

I am not sure how to handle this. If I just create a pointer to the structure, I cannot initialize its variables, right ? I need to somehow create a new client_entry and add it to the client_queue.

Thanks,

Can you expand a client snippet? I don't quite understand what client_entry_t client; actually is. Is it local var on some procedure? Is it itself shared? If so, how it is attached to the server address space?

Besides that, I am not sure that you may use pthread methods in this context.

Client queue address is shared, which is shm. I need to somehow add new clients, and update the queue's first and last pointers. Basically, when a new client is created, it creates a shared memory segment for another queue, and spawns threads to add requests. As soon as a server gets notified about a client, it spawns a new thread for servicing each client, and goes through the newly created queue. (Producer-consumer).

You need to 'allocate' your client data in the same shared memory as everything else (which is shared between the two processes).

Unless the shared memory is mapped to the same virtual address, pointers cannot be used (not easily anyway).

This article has been dead for over six months. Start a new discussion instead.