Project

General

Profile

Bug #20586 ยป readdir-bug-repro.c

ivoanjo (Ivo Anjo), 06/19/2024 01:57 PM

 
#include <dirent.h>
#include <errno.h>
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

volatile int signal_count = 0;

#define SIGNAL_TO_USE SIGPROF

void signal_handler(int _signal, siginfo_t *_info, void *_ucontext) {
signal_count++;
}

void *background_thread(void *main_thread_id) {
pthread_t main_tid = *(pthread_t *)main_thread_id;
while (1) {
pthread_kill(main_tid, SIGNAL_TO_USE);
}
return NULL;
}

int main(int argc, char *argv[]) {
if (argc < 2) {
fprintf(stderr, "Usage: %s <directory>\n", argv[0]);
exit(EXIT_FAILURE);
}

pthread_t tid;
pthread_t main_tid = pthread_self();

struct sigaction sa = { .sa_flags = SA_RESTART | SA_SIGINFO, .sa_sigaction = signal_handler };
sigemptyset(&sa.sa_mask);
sigaction(SIGNAL_TO_USE, &sa, NULL);

fprintf(stderr, "Set up signal handler!\n");

// Create the background thread
if (pthread_create(&tid, NULL, background_thread, &main_tid) != 0) {
perror("Failed to create thread");
exit(EXIT_FAILURE);
}

// Wait until at least one signal is received
while (signal_count == 0);

fprintf(stderr, "Received %d signals, calling readdir...\n", signal_count);

const char *path = argv[1];
DIR *dir = opendir(path);
if (dir == NULL) {
fprintf(stderr, "Failed to open directory '%s': %s\n", path, strerror(errno));
exit(EXIT_FAILURE);
}

struct dirent *entry;
int fileCount = 0;

while ((entry = readdir(dir)) != NULL) {
if (entry->d_type == DT_REG) { // Check if the entry is a regular file
fileCount++;
}
}

if (errno) { // Check if readdir() set errno
fprintf(stderr, "Failed to read directory '%s': %s\n", path, strerror(errno));
closedir(dir);
exit(EXIT_FAILURE);
}

printf("The directory '%s' contains %d files.\n", path, fileCount);

if (closedir(dir) < 0) {
fprintf(stderr, "Failed to close directory '%s': %s\n", path, strerror(errno));
exit(EXIT_FAILURE);
}

return EXIT_SUCCESS;
}
    (1-1/1)