I’m trying to write a program in c that uses threads to print out the contents of the current working directory. Currently the right number of files are printed, however, some files repeat multiple times. Which files repeat and how many times seems random every time I run it. I tried using a mutex lock on what I thought was the critical section, but to no success.
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
struct arg_struct
{
struct dirent *current;
struct stat buf;
};
void * mybackup (void *arguments)
{
pthread_mutex_lock( &mutex );
struct arg_struct *args = arguments;
printf( "[THREAD %u] ", (unsigned int)pthread_self());
printf( "%s ", args->current->d_name );
printf( "(%lld bytes)\n", (long long) args->buf.st_size );
total_bytes += args->buf.st_size;
pthread_mutex_unlock( &mutex );
return NULL;
}
int main (int argc, char **argv)
{
if (argc == 1) //For part 1, when no cmd line argument is given
{
int children = 0;
int thread, i;
pthread_t tid[100];
char * current_path = ".";
DIR * dir = opendir((char*)current_path); //Opens the current directory
if (dir == NULL) //Detects failure to open directory
{
perror("opendir() Failed");
return EXIT_FAILURE;
}
struct dirent *current;
int rc = 0;
while ((current = readdir(dir)) != NULL)
{
struct stat buf;
char new[10000]; //Used to create the complete path name
//Next few lines create the complete path name required for Stat()
strcpy(new, current_path);
strcat(new, "/");
strcat(new, (char*)current->d_name);
rc = stat(new, &buf);
//rc = stat(current -> d_name, &buf);
if (rc < 0) //Detects stat() failure
{
perror("stat() Failed");
return 1;
}
else
{
if (S_ISREG(buf.st_mode)) //If directory entry is a regular file
{
struct arg_struct args;
args.current = current;
args.buf = buf;
thread = pthread_create(&tid[children], NULL, mybackup, (void *)&args);
if ( thread != 0 )
{
perror( "MAIN: Could not create child thread" );
}
children++;
}
}
}
for (i = 0; i < children; i++)
{
pthread_join(tid[i], NULL);
}
printf("Total bytes: %lld\n", total_bytes);
}
return 0;
}
This can’t be right. The (stack-based) object you pass to the to the thread function it is very likely to be overwritten before the created thread has had a chance to do anything with it.
You’ll need to
mallocthat structure (and deal withfreeing), or use an array (on stack or static) of such structs that is large enough so that you can assign one to each of your threads.In fact, just allocating that structure’s not enough, you can’t pass the
dirent* currentas a pointer – you need to copy the data you need from it to your per-thread structure, or possibly usereaddir_rinstead (read the example in the man page carefully).