Reputation: 1
I am making a C program for Linux that is supposed to grab files from its current directory and append them to a common file. It's imperative that the process has an adjustable number of threads and that the threads are permanent, meaning they'll wait when they're done executing in case they need to execute again. The code below assigns an incoming file to the fastest thread, and the thread attempts to append the contents to the common file. However, the function 'copiar_archivo()' that I'm using to do so does not execute at all; the code skips the call to the function and proceeds to delete the file. What am I missing?
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <sys/inotify.h>
#define EVENT_SIZE (sizeof (struct inotify_event))
#define BUF_LEN (1024 * (EVENT_SIZE + 16))
#define NOM_FICH "FICHERO.csv"
void *hilo_func(void *arg);
void copiar_archivo(char *nombre_archivo_x, char *nombre_archivo_y);
int n_hilos = 2;
int fd, wd;
int main(void) {
pthread_t hilos[n_hilos];
int i, rc;
int thread_numbers[n_hilos];
fd = inotify_init();
if (fd < 0) {
perror("Error al inicializar inotify");
exit(EXIT_FAILURE);
}
wd = inotify_add_watch(fd, ".", IN_CREATE);
if (wd < 0) {
perror("Error al agregar directorio para observación");
exit(EXIT_FAILURE);
}
for (i = 0; i < n_hilos; i++) {
thread_numbers[i] = i + 1;
rc = pthread_create(&hilos[i], NULL, hilo_func, &thread_numbers[i]);
if (rc) {
perror("Error al crear hilo");
exit(EXIT_FAILURE);
}
}
for (i = 0; i < n_hilos; i++) {
rc = pthread_join(hilos[i], NULL);
if (rc) {
perror("Error al esperar hilo");
exit(EXIT_FAILURE);
}
}
inotify_rm_watch(fd, wd);
close(fd);
return 0;
}
void *hilo_func(void *arg) {
int num_hilo = *(int *) arg;
char buf[BUF_LEN];
int length, i = 0;
while (1) {
length = read(fd, buf, BUF_LEN);
printf("Hilo %d: AWARE\n", num_hilo);
if (length < 0) {
perror("Error al leer evento inotify");
exit(EXIT_FAILURE);
}
while (i < length) {
struct inotify_event *event = (struct inotify_event *) &buf[i];
if (event->mask & IN_CREATE) {
printf("Hilo %d: archivo '%s' creado\n", num_hilo, event->name);
//PROBLEM HERE
char nom_destino[100] = NOM_FICH;
copiar_archivo(event->name, nom_destino);
sleep(1);
remove(event->name);
}
i += EVENT_SIZE + event->len;
}
i = 0;
}
pthread_exit(NULL);
}
void copiar_archivo(char *nombre_archivo_x, char *nombre_archivo_y) {
printf("EY, al menos funciona :)");
FILE *archivo_x, *archivo_y;
char buffer[1024];
size_t n;
archivo_x = fopen(nombre_archivo_x, "rb");
if (archivo_x == NULL) {
perror("Error al abrir archivo X");
exit(EXIT_FAILURE);
}
archivo_y = fopen(nombre_archivo_y, "ab");
if (archivo_y == NULL) {
perror("Error al abrir archivo Y");
exit(EXIT_FAILURE);
}
while ((n = fread(buffer, 1, sizeof buffer, archivo_x)) > 0) {
fwrite(buffer, 1, n, archivo_y);
}
if (ferror(archivo_x)) {
perror("Error al leer archivo X");
exit(EXIT_FAILURE);
}
fclose(archivo_x);
fclose(archivo_y);
}
I have tried using the function 'copiar_archivo()' in main and using the exact name of the files to handle, which does work. I'm suspecting it has to do with using it inside a thread, or perhaps the inotify event.
Upvotes: 0
Views: 85
Reputation: 1865
The problem seems to be because when you create FICHERO.csv
in the same directory after starting watching, a second thread reacts to that and then deletes the file FICHERO.csv
giving the impression that the function was not executed.
Creating the destiny file before start watching would fix that part:
int main(void) {
pthread_t hilos[n_hilos];
int i, rc;
int thread_numbers[n_hilos];
fclose(fopen(NOM_FICH, "w")); // create empty file before watching
However, you have other issues, like writing to the same file at the same time in multiple threads. I guess this is only a test and in reality every file would be written to a different file, so for this test I would name the destiny file as the source in another directory.
You also don't need the thread_numbers
array, you could do with just one variable, in the scope of the for:
for (i = 0; i < n_hilos; i++) {
int thread_number = i + 1;
rc = pthread_create(&hilos[i], NULL, hilo_func, &thread_number);
Upvotes: 0