ABC
ABC

Reputation: 81

Scanf and printf with Semaphore System V

I can't understand why the output of my code is the following. It does not follow the logic I wrote in the program. I'm using System V semaphore to sync thread each others.

This program should simply require strings from standard input to the "main thread" and these should be written by child threads on files whose "pathname" is passed on to argv. FOR SIMPLICITY I removed this part and left only the scanf and printf, which resolved completely messed up by the logic of the program!

How do I solve it?

#define _GNU_SOURCE
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#define fflush(stdin) while(getchar()!='\n') //REMOVE THIS
void *gestore(void *);
char buf[10];
struct info
{
        pthread_t tid[100];
        int v[100];
};
struct info TID;
union semun
{
        int val;
        struct semid_ds *buf;
        unsigned short *array;
        struct seminfo *__buf;
};
int indice;
int id_sem;
void *gestore(void *str)
{
        int fd, i, j;
        struct sembuf op[1];
        printf("Thread(%ld) CREATED\n",syscall(SYS_gettid));
        fflush(stdout);
        fd = open((char *)(str),O_CREAT|O_RDWR,0666);
        if(fd==-1)
        {
                printf("Error\n");
                return;
        }
        else
        {
                printf("File Opened\n");
                fflush(stdout);
        }
        repeat:
        op[0].sem_num=0;
        op[0].sem_op=-1;
        op[0].sem_op=0;
        semop(id_sem,op,1);
        printf("HELLO\n");
        fflush(stdout);
        for(i=0; i<5; i++)
        {
                if(write(fd,&(buf[2*i]),1)==-1)
                {
                        printf("ErroreWrite\n");
                        fflush(stdout);
                        return;
                }
                else
                {
                        printf("WRITED\n");
                        fflush(stdout);
                }

        }
        op[0].sem_num=1;
        op[0].sem_op=1;
        op[0].sem_op=0;
        semop(id_sem,op,1);
        goto repeat;

        if(close(fd)==-1)
        {
                printf("Errore close\n");
                return;
        }
        else
        {
                printf("File CLOSED\n");
                fflush(stdout);
        }

}



int main(int argc, char *argv[])
{
        if(argc<2)
        {
                printf("There must be at least 2 parameters\n");
                fflush(stdout);
                return -1;
        }
        int i;
        indice = argc;
        printf("Number of arguments:%d \n",argc);
        fflush(stdout);

        //SEM SYSTEM V

        union semun arg;
        struct sembuf op[1];
        id_sem = semget(6534,2,IPC_CREAT|0666);
        arg.val=0;
        semctl(id_sem,0,SETVAL,arg);
        arg.val=1;
        semctl(id_sem,1,SETVAL,arg);
        //////////////////////


        for(i=0; i<(argc-1); i++)
        {
                pthread_create(&(TID.tid[i]),NULL,gestore,argv[i+1]);
        }
        while(1)
        {
                op[0].sem_num=1;
                op[0].sem_op=-1;
                op[0].sem_op=0;
                semop(id_sem,op,1);

                for(i=0;i<5;i++)
                {
                        printf("Insert value(%d): \n",i);
                        fflush(stdout);
                        scanf("%c",&(buf[2*i]));
                        buf[2*i+1]='\0';
                        fflush(stdin);//USE while(getchar()!='\n');
                }

                op[0].sem_num=0;
                op[0].sem_op=1;
                op[0].sem_op=0;
                semop(id_sem,op,1);
        }

}

(a, b, c, d, e, f, g is my input from stdin)

Here is my output:

Number of arguments:4
a
Thread(1048) CREATED
Thread(1049) CREATED
Thread(1050) CREATED
b
File OPENED
c
File OPENED
d
File OPENED
e
f
HELLO
g
HELLO
h
WRITED
i
WRITED
l
WRITED
m
WRITED
n
WRITED
o
WRITED
p
WRITED
q
WRITED
e
WRITED
r
WRITED
s
a
s

Where is my string "Insert Value(%d)..."?

Replacing the macro defined by me with fflus (stdin) the following writing: while (getchar ()! = 'N'); the output obtained is:

Number of arguments:4
Thread(1090) CREATED
Thread(1091) CREATED
Thread(1092) CREATED
File OPENED
File OPENED
HELLO
File OPENED
WRITED
HELLO
WRITED
WRITED
WRITED
WRITED
WRITED
WRITED
WRITED
WRITED
WRITED

In this case I got these outputs without sending any input characters.

Upvotes: 1

Views: 316

Answers (2)

ABC
ABC

Reputation: 81

Found the mystery. The triplet:

  • op[0].sem_num=0;
  • op[0].sem_op=-1;
  • op[0].sem_flg=0;

It was written everywhere badly in the following way:

  • op[0].sem_num=0;
  • op[0].sem_op=-1;
  • op[0].sem_op=0; <---------

Also associated with the incorrect definition that other users pointed out to me was a disaster.

Thank you all!

Upvotes: 1

klutt
klutt

Reputation: 31389

Don't know if it will solve your problem, but your code is SERIOUSLY flawed with your define. Not only is it confusing for readers who knows that flushing stdin is a big nono. It also alters all calls to fflush, no matter the argument. Here is a Hello World program to demonstrate:

#include <stdio.h>
#define fflush(stdin) printf("Hello, World!\n")

int main(void)
{
    // Will call above macro despite the fact that I'm trying to flush stdout
    fflush(stdout);
}

If you want to use a macro, do something like this:

#define FLUSH_STDIN while(getchar()!='\n')

But unless you have a good reason to use a macro, use a function:

void flush_stdin(void) { while(getchar()!='\n'); }

I would also advice against using identifiers starting with underscore (struct seminfo *__buf;) since these are reserved in C.

Upvotes: 0

Related Questions