Thread: adding the filenames of the current directory to an array

  1. #1
    Registered User
    Join Date
    Nov 2011
    Posts
    6

    adding the filenames of the current directory to an array

    So I am attempting to implement a pipelined multi-threaded version of the grep command. Currently this is what I have:
    Code:
    void *stage1(void *arg)
    {
        DIR *dir;
        struct dirent *ent;
        dir = opendir (".");
        if (dir != NULL) {
    
          while ((ent = readdir (dir)) != NULL) {
            printf ("%s\n", ent->d_name);
          }
          closedir (dir);
        } else {
            printf("FAILURE");
        }
    }
    This is the method that the first thread runs. I have the printf line just for debugging purposes. Currently nothing is displayed on the terminal when I run the program. Once I get this issue resolved I will replace the printf line with:
    buff1[wp] = ent;
    wp++;
    where wp is a pointer that points to the next available spot in the char buffer, buff1. I will have more code to ensure that the pointer is always correct but this is what I'm working with for now.

    I know very little with c and have been spending the past 3 days reading as much as I can but I can't figure out why this doesn't print anything to the terminal. Using a debugger I've determined that the program never enters the while loop but I can't really figure out why.

  2. #2
    Registered User
    Join Date
    Nov 2011
    Location
    Saratoga, California, USA
    Posts
    334
    readdir() is not reentrant. Use readdir_r().

  3. #3
    Registered User
    Join Date
    Nov 2011
    Posts
    6
    So the excerpt above works perfectly fine in the main method but it doesn't work as the thread's main method....

    Here is my full code:

    Code:
    #include <pthread.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <dirent.h>
    
    pthread_mutex_t mut1 = PTHREAD_MUTEX_INITIALIZER,
                    mut2 = PTHREAD_MUTEX_INITIALIZER, 
                    mut3 = PTHREAD_MUTEX_INITIALIZER,
                    mut4 = PTHREAD_MUTEX_INITIALIZER;
    char *buff1, *buff2, *buff3, *buff4;
    
    void *stage1(void *arg)
    {
    DIR *dir = (DIR*)arg
        struct dirent *ent;
        if (dir != NULL) 
        {
          while ((ent = readdir (dir)) != NULL) 
          {
            printf ("%s\n", ent->d_name);
          }
          closedir (dir);
        } else
        {
            printf("FAILURE");
        }
    }
    
    int main(int argc, char *argv[])
    {
            if(argc != 6)
        {
          printf("Usage: %s <buffsize> <filesize> <uid> <gid> <string>\n", argv[0]);
          return(-1);
        }
    
        int buffsize, filesize, uid, gid;
        sscanf(argv[1],"%d",&buffsize);
        sscanf(argv[2],"%d",&filesize);
        sscanf(argv[3],"%d",&uid);
        sscanf(argv[4],"%d",&gid);
        
        char *string = argv[5];
        
        buff1 = malloc(buffsize * sizeof(*buff1));
        buff2 = malloc(buffsize * sizeof(*buff2));
        buff3 = malloc(buffsize * sizeof(*buff3));
        buff4 = malloc(buffsize * sizeof(*buff4));
    
        pthread_t th1,th2,th3,th4,th5;
            
            DIR *dir = opendir(".");
    
        pthread_create(&th1,NULL,stage1,dir);
    
        if(filesize != -1) pthread_create(&th2,NULL,stage2,buff2);
        
        return 0;
    }
    This seems to work when run in the debugger but when i try ./pipegrep 1 2 3 4 abc it doesn't print a thing.
    Last edited by shade963; 11-22-2011 at 10:12 PM.

  4. #4
    Registered User
    Join Date
    Nov 2011
    Posts
    6
    I don't see why i need it to be reentrant I only want it to get the file names once

  5. #5
    Registered User
    Join Date
    Nov 2011
    Posts
    63
    I got this to work. Here's some tips: Strengthen your compiler warnings! I used -ansi -pedantic -Wall -Werror for error checking and I used -pthread instead of -lpthread for linking (In the past I used -lpthread). You have quite a few errors and you do virtually no error checking.

    The reason this fails though is that main doesn't wait for threads to finish. Once your OS scheduler context switches back to the main thread, main doesn't care whether or not any child threads are running when it hits the return statement. Open your terminal and type man pthread_join. That command should help you out. You may want to create thread_attr_t's to make sure your threads are explicitly joinable. Lookup pthread_attr_setdetachstate for information on that. The following code works for me.

    NOTE: No error checking and other bad practices are shown.
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <dirent.h>
    #include <pthread.h>
    
    char *buff1, *buff2, *buff3, *buff4;
    
    void *stage1(void *arg)
    {
        struct dirent *ent;
        DIR *dir = (DIR*)arg;
        
        if (dir != NULL) 
        {
          while ((ent = readdir (dir)) != NULL) 
          {
            printf ("%s\n", ent->d_name);
          }
          closedir (dir);
        } else
        {
            printf("FAILURE");
        }
        
        pthread_exit(NULL);
    }
    
    int main(int argc, char *argv[])
    {
        int buffsize, filesize, uid, gid;
        pthread_t th1;
        DIR *dir = opendir(".");
        
        if(argc != 6)
        {
          printf("Usage: %s <buffsize> <filesize> <uid> <gid> <string>\n", argv[0]);
          return(-1);
        }
    
        
        sscanf(argv[1],"%d",&buffsize);
        sscanf(argv[2],"%d",&filesize);
        sscanf(argv[3],"%d",&uid);
        sscanf(argv[4],"%d",&gid);
        
        buff1 = malloc(buffsize * sizeof(*buff1));
        buff2 = malloc(buffsize * sizeof(*buff2));
        buff3 = malloc(buffsize * sizeof(*buff3));
        buff4 = malloc(buffsize * sizeof(*buff4));
        
        pthread_create(&th1, NULL, stage1, (void *) dir);
        pthread_join(th1, NULL);
        
        return 0; /* main is also a thread, so you could use pthread_exit(NULL); here instead */
    }
    On my system, this compiles and outputs the correct information with these flags:

    Code:
    gcc -ansi -pedantic -Wall -Werror -pthread -O0 -g -o custom_grep custom_grep.c
    Last edited by failure67; 11-22-2011 at 11:53 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Help needed to get list of filenames in directory to an array
    By Sabarigirshm in forum C Programming
    Replies: 15
    Last Post: 04-28-2011, 05:10 PM
  2. Replies: 6
    Last Post: 04-30-2010, 06:13 PM
  3. Retrieving Filenames from a directory.
    By Raigne in forum C++ Programming
    Replies: 8
    Last Post: 05-17-2007, 08:05 PM
  4. Filenames in a directory
    By devour89 in forum C++ Programming
    Replies: 1
    Last Post: 01-25-2003, 07:49 AM
  5. Replies: 2
    Last Post: 04-14-2002, 01:03 PM