开发者

Bus error with semaphore func semctl() in this code running on Solaris

This is my first attempt on semaphores and threads. I constructed this code from examples and the man pages found on the Net. I have two doubts with this code.

  1. Why do I get a Bus error whenever I try semctl( I know this is the root of the problem because of the debug line 3 does not get printed) and how to prevent it?

  2. Why am I not able to acquire a lock on my critical section inspite of removing semctl()?

I am trying to execute the following code:

#include <stdio.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/sem.h>

#define NUM 3
char c='a';
int semId=-1;
struct sembuf lockOperation = { 0, -1, 0};
struct sembuf unlockOperation = { 0, -1, 0};

void* PrintLetter()
{
  int rc;

  rc=semop(semId, &lockOperation, 1);

  if(rc)
    {
      printf("\n Unable to lock\n");
      exit(1);
    }
  printf("%c",c);    //CRITICAL SECTION
  c=c+1;             //CRITICAL SECTION  
  rc = semop(semId, &unlockOperation, 1);
  if(rc)
    {
      printf("\n Unable to unlock\n");
      exit(1);
    }

  pthread_exit(NULL);

}
int main()
{
  pthread_t threads[NUM];

  int rc=1;
  long t;
   printf("debug line 1\n");
  semId = semget(IPC_PRIVATE, 1, IPC_CREAT|IPC_EXCL);
  if( semId == -1)
    {
      printf("\n Error in making the sem\n");
      exit(1);
    }
  printf("debug line 2\n");
  rc = semctl(semId, 0, SETVAL, (int)1); // Comment from here

  if(rc)
    {
      printf("\n Unable to set val to 1\n");
      exit(1);
      }    ////////////////////////////////// till here
   printf("debug line 3\n");


  for(t=0; t<NUM; t++){
    printf("In main: creating thread %ld\n", t);
    rc = pthread_create(&threads[t], NULL, PrintLetter, NULL);
    if (rc){
      printf("ERROR; return code from pthread_create() is %d\n", rc);
      exit(-1);
    }
    sleep(3);
  }
  pthread_exit(NULL);
}

NOTE: I added the following to the code after suggestion:

union semun {
  int              val;    /* Value for SETVAL */
  struct semid_ds *buf;    /* Buffer for IPC_STAT, IPC_SET */
  unsigned short  *array;  /* Array for GETALL, SETALL */
  struct seminfo  *__buf;  /* Buffer for IPC_INFO
                              (Linux specific) */
};

Also added the following:

union semun s_u;
s_u.val=1;

Changed the semctl line to

rc = semctl(semId, 0, SETVAL, s_u);

and made all rc checks to:

if(rc == -1)

semctl() line still does not execute sucessfully. The errno now states : Permission Denied

UPDATE: I am able to get rid off the "Permission Denied" error using the following change:

semId = semget(IPC_PRIVATE, 1, IPC_CREAT|IPC_EXCL|0660);

Now , the new prob开发者_JS百科lem is that, I am unable to print "abc" on the console. The program just prints "a" and hangs. Not sure why.

Final UPDATE: I messed up in the Unlock code: i used -1 instead of 1 Here is the new code:

struct sembuf unlockOperation = { 0, 1, 0};

I thank you all for your help and patience.


The fourth argument to semctl (if present) should be of type union semun:

union semun {
            int val;
            struct semid_ds *buf;
            unsigned short  *array;
} arg;

Maybe passing an int there instead is causing alignment problems.


Before you do anything else, correct your error handling code. This is wrong:

rc = semop(semId, &lockOperation, 1);

if (rc)
{
    printf("\n Unable to lock\n");
    exit(1);
}

Semop() and semctl() return -1 on error so it should be something like

rc = semctl(semId, 0, SETVAL, (int)1); // Comment from here

if (rc == -1)
{
    perror("SETVAL");
    exit(1);
}

This get confusing because the pthread API returns 0 on success and an error number otherwise. It is easy to get them confused so be careful.


Try to pass explicit semun union to semctl, rather than rvalue 1. probably should not matter, but who knows.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜