Question

The revelant code may be found here: http://pastebin.com/VbhtQckm
The problem is at line 85. pthread_mutex_lock(ID_retrieval_pool->info->lock);

I'm running the server and it's getting stuck at lock. The memory is allocated, I'm initializing the mutex and it's the only thread who's owning that shared memory.
I did debug with GDB and Valgrind using helgrind tool but did not find any clue. Possible problems which think may cause this:

  • mutex is not being initialized (I'm using a block is shared memory which I'm initializing as a mutex);
  • deadlock? in the man page https://www.sourceware.org/pthreads- win32/manual/pthread_mutex_init.html says this can cause this;

Please note that this code is for learning purpose.

Edit, the code is:

// common_header.h + common_header.c
#ifndef DATA_TYPES_H
#define DATA_TYPES_H

#include <pthread.h>
#include <errno.h>

#define RETREIVE_ID_KEY 1

typedef enum {
  SHM_State_None,
  SHM_State_ID_Available,
  SHM_State_ID_Not_Available,
} SHM_State;

typedef struct {
    pthread_mutex_t *lock; // locked if any thread is modifying data
    SHM_State state;
} data_state;

typedef int shmid_t;

typedef struct data_pool {
    data_state *info;
    shmid_t shm_id;
} data_pool;

// other data structures

extern data_state * data_state_initialize_by_setting_address(void *address)
{
  data_state *data = (data_state *)address;
  data->lock = (pthread_mutex_t *)address;
  pthread_mutex_init(data->lock, NULL);
  data->state = SHM_State_None;

  return data;
}
extern data_pool * data_pool_initialize_by_setting_address(void *address)
{
  data_pool *data = (data_pool *)address;
  data->info = data_state_initialize_by_setting_address(address);
  data->shm_id = 0; // invalid though, the structure's client has to set a valid one

  return data;
}
// other initialization functions

#endif // DATA_TYPES_H

///----------------------------------------------------------------------------------------\\\

// main.c -- Server
#include "common_header.h"

#define SHM_INVALID_ADDRESS (void *)-1
#define SHMGET_RW_FLAGS 0666
#define SHMAT_RW_FLAGS 0

bool initialize_data();

static data_pool *ID_retrieval_pool = NULL;

int main(int argc, char *argv[])
{
  if (!initialize_data()) {
    return EXIT_FAILURE;
  }
  // Do other stuff

  return EXIT_SUCCESS;
}

bool initialize_data()
{
  // some irrelevant initialization code
  shmid_t shm_ID = shmget(RETREIVE_ID_KEY,
                          sizeof(data_pool),
                          IPC_CREAT | SHMGET_RW_FLAGS);
  void *shm_address = shmat(shm_ID, NULL, SHMAT_RW_FLAGS);
  if (shm_address == SHM_INVALID_ADDRESS) {
    return false;
  }
  ID_retrieval_pool = data_pool_initialize_by_setting_address(shm_address);
  pthread_mutex_lock(ID_retrieval_pool->info->lock);
  ID_retrieval_pool->shm_id = get_shared_ID();
  ID_retrieval_pool->info->state = SHM_State_ID_Available;
  pthread_mutex_unlock(ID_retrieval_pool->info->lock);

  // other initialization code

  return true;
}
Was it helpful?

Solution

You have an interesting and incorrect way of initializing the mutex:

data->lock = (pthread_mutex_t *)address; /* address == &data */
pthread_mutex_init(data->lock, NULL);

In your code address is the address of the outer struct: this does not actually allocate a usable block of memory.

I suggest you just make the mutex non-pointer and then initialize it:

/* In the struct. */
pthread_mutex_t lock;

/* In your function. */
pthread_mutex_init(&data->lock, NULL);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top