few days ago I started working on the sleeping barber problem, got some issues with segmentation fault But they have been solved here
Even though I fixed the missing parts, I still have a problem. I need to use FIFO queue, and create shared memory for it. I get no errors when creating it. Running the client should let me put clientAmount
of clients into the queue, from which barber should be getting them. Every client is described by his process id. But when I try to do so, client program shows that clients have been added to queue:
2101 entered the queue
2099 entered the queue
2104 entered the queue
2097 entered the queue
2103 entered the queue
2095 entered the queue
2102 entered the queue
2098 entered the queue
2096 entered the queue
but when I run the barber code, all I get is:
Queue empty, I fall asleep
I'm waking up
Queue empty, I fall asleep
I'm waking up
Queue empty, I fall asleep
I'm waking up
Queue empty, I fall asleep
I'm waking up
Queue empty, I fall asleep
I'm waking up
Queue empty, I fall asleep
I'm waking up
Queue empty, I fall asleep
I'm waking up
Queue empty, I fall asleep
I'm waking up
I'm not really sure what to do here.
The code for client:
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "functions.h"
#include <sys/mman.h>
#include <unistd.h>
#include <signal.h>
int numberOfCuts;
int isCut;
int isDone;
void status(int f);
int main(int argc,char* argv[])
{
if(argc < 3){
printf("Error while executing program, invalid amount of arguments");
return 0;
}
sem_t *barber;
sem_t *queue;
sem_t *client;
sem_t *pillow;
int clientsAmount;
int sharedmem, waitRoomSize;
struct Queue* waitroom;
void *space;
int i;
signal(SIGUSR1, status);
clientsAmount = atoi(argv[1]);
numberOfCuts = atoi(argv[4]);
barber = sem_open("/B", O_RDWR);
if((barber == SEM_FAILED)){
perror("Error while getting semaphore for barber");
exit(1);
}
queue = sem_open("/Q", O_RDWR);
if((queue == SEM_FAILED)) {
perror("Error while creating semaphore for queue");
exit(1);
}
client = sem_open("/C", O_RDWR);
if(client == SEM_FAILED){
perror("Error while creating semaphore for pillow");
exit(0);
}
sharedmem = shm_open("QueueMem", O_RDWR, 0666);
if(sharedmem==-1){
perror("Error while getting shared memory");
exit(1);
}
space = mmap(NULL, sizeof(waitroom), PROT_READ | PROT_WRITE, MAP_SHARED, sharedmem, 0);
if((space == MAP_FAILED)){
perror("Error while mapping memory");
exit(1);
}
waitroom = (struct Queue*) space;
for(i = 0; i< clientsAmount; i++){
if(fork() == 0){
int isCut = 0;
int id = getpid();
printf("%d entered the queue \n", id);
sem_wait(queue);
sem_post(queue);
if( push(waitroom, id)==-1){
printf("Queue is full, leaving...");
exit(0);
}else {
push(waitroom, id);
sem_wait(pillow);
printf("%d: Barber is sleeping, he needs to wake up", id);
int x;
sem_getvalue(barber, &x);
if(x==0){
sem_post(barber);
while(x!= 0){
sem_post(barber);
printf("Barber is waking up to cut %d", id);
}
}
sem_post(pillow);
_exit(0);
}
}
}
sem_close(barber);
sem_unlink("/B");
sem_close(queue);
sem_unlink("/Q");
sem_close(client);
sem_unlink("/C");
}
void status(int f){
numberOfCuts--;
printf("Remaining cuts: %d", numberOfCuts);
isCut = 1;
while(!numberOfCuts)
{
printf("Leaving the barber");
isDone =1;
}
}
The barber code:
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "functions.h"
#include <sys/mman.h>
#include <unistd.h>
#include <signal.h>
#define BARBER "Barber"
int main(int argc,char* argv[])
{
if(argc < 2){
printf("Error while executing program, invalid amount of arguments");
return 0;
}
sem_t *barber;
sem_t *queue;
sem_t *client;
int seats;
int sharedmem, waitRoomSize;
struct Queue* waitroom;
queue = sem_open("/Q", O_CREAT | O_RDWR, 0666, 1);
if((queue == SEM_FAILED)) {
printf("Error while creating semaphore for queue");
exit(1);
}
barber= sem_open("/B", O_CREAT | O_RDWR, 0666, 1);
if((barber == SEM_FAILED)){
printf("Error while creating semaphore for barber");
exit(1);
}
client = sem_open("/C", O_CREAT | O_RDWR, 0666, 0);
if(client == SEM_FAILED){
printf("Error while creating semaphore for pillow");
exit(0);
}
seats = atoi(argv[1]);
void *space;
sharedmem = shm_open("Queue",O_CREAT | O_RDWR, 0666);
if(sharedmem==-1){
printf("Error while getting shared memory");
exit(1);
}
waitRoomSize = ftruncate(sharedmem, sizeof(waitroom));
if((waitRoomSize ==-1)){
printf("Error while getting size");
exit(1);
}
space = mmap(NULL, sizeof(struct Queue), PROT_READ | PROT_WRITE, MAP_SHARED, sharedmem, 0);
if((space == MAP_FAILED)){
printf("Bład podczas mapowania pamiêci");
exit(1);
}
waitroom = (struct Queue*) space;
queueinit(waitroom, seats);
printf("semaphores created\n");
while(1)
{
sem_post(queue);
int x = isEmpty(waitroom);
sem_wait(queue);
if(x==1){
printf("Queue empty, I fall asleep\n");
sem_post(barber);
sem_wait(barber);
printf("I'm waking up\n");
} else {
sem_post(queue);
int id = get(waitroom);
sem_wait(queue);
printf("%d, please sit on the chair\n", id);
printf("Started cutting hair for %d\n", id);
sleep(2);
printf("Cutting done for :%d \n", id);
kill(id, SIGUSR1);
}
}
sem_close(barber);
sem_unlink("/B");
sem_close(queue);
sem_unlink("/Q");
sem_close(client);
sem_unlink("/C");
printf("senaphores unlinked");
}
The code for queue:
#ifndef FUNCTIONS_H_INCLUDED
#define FUNCTIONS_H_INCLUDED
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "functions.h"
#include <sys/mman.h>
#include <unistd.h>
#include <signal.h>
struct Queue{
int elems[500];
int size;
int queueIn;
int queueOut;
int isAsleep;
int mainPID;
int countCurrent;
};
void queueinit(struct Queue* q, int size){
q->size = size;
q->queueIn = q->queueOut = 0;
q->isAsleep = 0;
q->countCurrent = 0;
}
int push(struct Queue* q, int e){
if(q->queueIn == ((q->queueOut -1 + q->size) % q->size)){
return -1; //Queue full
}
q->elems[q->queueIn] = e;
q->queueIn = (q->queueIn + 1) % q->size;
return 0;
}
int get(struct Queue* q){
int e = q->elems[q->queueOut];
q->queueOut = (q->queueOut + 1) % q->size;
return e;
}
int isEmpty(struct Queue* q){
if(q->queueIn == q->queueOut)
return 1;
return 0;
}
void lock(sem_t* sem){
if(sem_wait(sem) == -1){
printf("Error while lockin semaphore");
exit(1);
}
}
void free_sem(sem_t* sem){
if(sem_post(sem) == -1){
printf("Error while releasing semaphore");
exit(1);
}
}
#endif // FUNCTIONS_H_INCLUDED
Any suggestion would be greatly appreciated
EDIT As of now, few changed have been added:
- Checking the return value of
sem_wait
andsem_post
- Removed the second call for
push(waitroom, id)
in client - Took care of locking and unlocking semaphores, mainly swapped
sem_wait
withsem_post
and vice versa - Got rid of the pillow semaphore
Now the program was working nearly fine, however the client code did not exit after all its children finished their work. Pressing [ENTER]
works. So I took the given advice and created a new semaphore - p
, which I lock instead of using pause()
in client code, and I unlock it in signal handler status()
. I also cahnged the value with which barber
semaphore was initialized - no more double locking or freeing a semaphore.
I also tried to use abort()
function instead of exit but it didn't work.
What happens now:
- Barber code does start but nothing happens.
- Client code starts and adds some values to queue, and immediately exits.
The updated code for barber:
#include <stdlib.h>
#include <semaphore.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "functions.h"
#include <sys/mman.h>
#include <unistd.h>
#include <signal.h>
#define BARBER "Barber"
int main(int argc,char* argv[])
{
if(argc < 2){
printf("Error while executing program, invalid amount of arguments");
return 0;
}
sem_t *barber;
sem_t *queue;
sem_t *p;
int seats;
int sharedmem, waitRoomSize;
struct Queue* waitroom;
queue = sem_open("/Q", O_CREAT | O_RDWR, 0666, 1);
if((queue == SEM_FAILED)) {
printf("Error while creating semaphore for queue");
exit(1);
}
barber= sem_open("/B", O_CREAT | O_RDWR, 0666, 0);
if((barber == SEM_FAILED)){
printf("Error while creating semaphore for barber");
exit(1);
}
p= sem_open("/P", O_CREAT | O_RDWR, 0666, 0);
if((p == SEM_FAILED)){
printf("Error while creating semaphore for barber");
exit(1);
}
seats = atoi(argv[1]);
void *space;
sharedmem = shm_open("QueueMem",O_CREAT | O_RDWR, 0666);
if(sharedmem==-1){
printf("Error while getting shared memory");
exit(1);
}
waitRoomSize = ftruncate(sharedmem, sizeof(waitroom));
if((waitRoomSize ==-1)){
printf("Error while getting size");
exit(1);
}
space = mmap(NULL, sizeof(struct Queue), PROT_READ | PROT_WRITE, MAP_SHARED, sharedmem, 0);
if((space == MAP_FAILED)){
printf("Error while mapping memory");
exit(1);
}
waitroom = (struct Queue*) space;
queueinit(waitroom, seats);
while(1)
{
lock(queue);
if(isEmpty(waitroom)==1){
printf("Queue empty, I fall asleep\n");
waitroom->isAsleep = 1;
free_sem(queue);
lock(barber);
printf("I'm waking up\n");
} else {
int id = get(waitroom);
free_sem(queue);
printf("%d, please sit on the chair\n", id);
printf("Started cutting hair for %d\n", id);
sleep(2);
printf("Cutting done for :%d \n", id);
kill(id, SIGUSR1);
}
}
sem_close(barber);
sem_unlink("/B");
sem_close(queue);
sem_unlink("/Q");
sem_close(p);
sem_unlink("/P");
//exit(0);
//printf("senaphores unlinked");
}
The updated code for client:
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "functions.h"
#include <sys/mman.h>
#include <unistd.h>
#include <signal.h>
int numberOfCuts;
#include "functions.h"
int id;
sem_t *barber;
sem_t *queue;
sem_t *p;
int clientsAmount;
int sharedmem, waitRoomSize;
struct Queue* waitroom;
void *space;
void status(int f);
void handler(int f);
int main(int argc,char* argv[])
{
if(argc < 3){
printf("Error while executing program, invalid amount of arguments");
return 0;
}
int i;
signal(SIGUSR1, status);
signal(SIGINT, handler);
int pid = getpid();
clientsAmount = atoi(argv[1]);
numberOfCuts = atoi(argv[2]);
barber = sem_open("/B", O_RDWR);
if((barber == SEM_FAILED)){
perror("Error while getting semaphore for barber");
exit(1);
}
queue = sem_open("/Q", O_RDWR);
if((queue == SEM_FAILED)) {
perror("Error while creating semaphore for queue");
exit(1);
}
p = sem_open("/P", O_RDWR);
if((p == SEM_FAILED)) {
perror("Error while creating semaphore for queue");
exit(1);
}
sharedmem = shm_open("QueueMem", O_RDWR, 0666);
if(sharedmem==-1){
perror("Error while getting shared memory");
exit(1);
}
space = mmap(NULL, sizeof(waitroom), PROT_READ | PROT_WRITE, MAP_SHARED, sharedmem, 0);
if((space == MAP_FAILED)){
perror("Error while mapping memory");
exit(1);
}
waitroom = (struct Queue*) space;
for(i = 0; i< clientsAmount; i++) {
if(fork() == 0) {
id = getpid();
printf("%d entered the barbershop \n", id);
while(1) {
lock(queue);
if( push(waitroom, id)==-1 ) {
free_sem(queue);
printf("Queue is full, %d leaving...\n", id);
exit(0);
} else {
free_sem(queue);
printf("%d has entered the queue \n", id);
lock(queue);
int x;
x = waitroom->isAsleep;
if(x==1){
printf("%d: Barber is sleeping, he needs to wake up\n", id);
waitroom->isAsleep = 0;
free_sem(queue);
free_sem(barber);
printf("Barber is waking up to cut %d\n", id);
} else {
printf("Barber is cutting someone else, %d waiting for its turn", id);
free_sem(queue);
}
}
lock(p);
}
break;
}
}
//exit(0);
sem_close(barber);
sem_close(queue);
sem_close(p);
munmap(space, waitRoomSize);
exit(0);
}
void handler(int f) {
printf("Closing");
sem_close(barber);
sem_close(queue);
munmap(space, waitRoomSize);
exit(0);
}
void status(int f) {
numberOfCuts--;
free_sem(p);
printf("Remaining cuts for %d: %d\n", id, numberOfCuts);
if(!numberOfCuts) {
printf("%d is done cutting \n", id);
exit(0);
}
}