mardi 21 juin 2016

Read doesn't block while pipe is empty? - C

i'm having problems between two childrens. Both of them calls the same function that work like this:

extern void filter_aux(char* filter_name)
{
    char bufferino_in [4096];
    char bufferino_out[4096];
    char cmdbuf[256];
    void *descriptor_lib;
    char dir_filter[1024];
    strcpy(dir_filter, "./");
    strcat(dir_filter,filter_name);
    tratar_t *pointer;  
    int contador = 0, leidos=0, i, fd;

    if (!strcmp(filter_name + strlen(filter_name) - 3, ".so")){

    if (!(descriptor_lib=dlopen(dir_filter, RTLD_LAZY))) {
        printf("dlopen failedn");
        fprintf(stderr, MYNAME": %sn", dlerror());

    }//if




    if (!(pointer=dlsym(descriptor_lib, "process"))) {
        printf("We can't open process");
    fprintf(stderr, MYNAME": %sn", dlerror());

    }

    printf("I'm the children: %d with actual_pid: %d and i'm going to try to read from the pipen", getpid(), pid_actual);

while((readed=read(pp[actual_p][0], bufferino_in,4096))>0){

    if(actual_p==n_filters-1){ /*This is the last filter*/
            printf("Number of chars that has been filtered: %dn", count=(*pointer)(bufferino_in, bufferino_out, readed)); 
            write(1,bufferino_out,count);
            printf("n");
    }//if
    else { /*These are not the last filter*/
            count=(*pointer)(bufferino_in, bufferino_out, readed); 
            write(pp[actual_p+1][1],bufferino_out,count);
            printf("n");
    }//if
}//while
    printf("I left the while and i'm the children %dn",getpid());

So the thing is in other function the parent, is writing characters to the first pipe[0][1], so the first childrens comes, read the Pipe, and enter in the function pointer. The return is the text filtered. I tried only with 1 children and pointer returns all perfect in bufferino_out and write it on stdout.

But when I try with 2 childs. The first one, read the pipe[0][0], and its suppose to write in the pipe[1][1], so the second children can read it.

The problem is when the second chidren reach the first line:

while((readed=read(pp[actual_p][0], bufferino_in,4096))>0){

He directly jumps outside the while, instead of stay blocked at the read() waiting for something to read in the pipe.

I don't know how to fix this.

By the way, actual_p its a variable that his value can be: 0,1...etc depend on the children, if its the first one created its 0, if its the second 1...etc

Hope you can help me, if you need more code informatión I can give to you.

EDIT1: This code is how i make the pipes and the forks.

void childrens_pipes (void)
{
int i, j, aux;
    pid_t p;


    printf("We make %d pipesn", n_filters);
    for (i=0;i<n_filters;i++){
            pp[i]= (int*)malloc(sizeof(int)*2);
            if (pipe(pp[i]) < 0) 
            {
                    perror("Error in pipe()"); exit(1);
            }//if


    }//for

    for (i=0;i<n_filters;i++){
        printf("I'm the father with pid: %d and I'm going to do a fork()n", getpid());
            switch(p=fork())
    {
    case -1:
        perror("fork() failedn");
                exit(1);
    case  0:


                actual_p=i;
                printf("I'm the children with pid: %d and i'm going to close the pipes I will not usen", getpid());
                for (aux=0;aux<n_filtros;aux++){ 
                        if(aux==actual_p){
                            printf("Close the pipe %d of writing %dn", aux, getpid());
                                close(pp[aux][1]);
                        }//if
                        else if(aux==actual_p+1){
                            printf("We close the pipe %d of reading %dn", aux, getpid());
                                close(pp[aux][0]);
                        }//else if
                        else {
                            printf("I close the pipe %d n", aux);
                            close(pp[aux][0]);
                            close(pp[aux][1]);
                        }//else

                }//for


        if(n_filtros > 0 && !strcmp(filters[i] + strlen(filters[i]) - 3, ".so"))    
        {   
                            compile_so(filters[i]);
                            filter_aux(filters[i]);
                            exit(0);
        }//if
        else
        {   /*This is a normal cmd call - I didn't finish this part*/

                        filter_aux(filters[i]);
                        exit(0);
        }//else

            default:
                printf("We close the parents pipes that we don't needn");
                close(pp[0][0]);
                for (j=1;j<n_filters;j++){
                    close(pp[j][0]);
                    close(pp[j][1]);

                }//for


    }//switch
    }//for
 }

Now it comes the function I call from *pointer in the first code (I tried to call it 2 times, 1 in each children, cause it should do the same of calling only 1 time).

#include <stdio.h>
#include <ctype.h>
#include <unistd.h>

int process(char* buff_in, char* buff_out, int leng)
{
    int i = 0, j=0, counter=0;
    char c;
    printf("------------------------  We are on process %d ---------------------------n",getpid());
    for(i=0;i<tam;i++){
                c = buff_in[i];
                    if(!isalpha(c)) {
                        counter++;
                        buff_out[j++]=c;
                    }//if
    }//for
printf("------------------------  We get out of Process  ---------------------------- readed= %d %dn", leng,getpid());
return counter;     

}

EDIT2: It seems that I failed to write in pp[1][1] in this sentence: write(pp[actual_p+1][1],bufferino_out,count); I don't know why.

Aucun commentaire:

Enregistrer un commentaire