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.
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?
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.
精彩评论