質問

I'm having a bit of a problem using Inotify. I'm watching a configuration file, looking to reload the configurations in case of modification. The modification is detected without trouble, but when I read the config values I get the old values. Let'say I have

attrib=value 

and I modify it so it's

attrib =value1

Then, when I read the file again I'd get "value" instead of "value1". And if I modified attrib again, when reading I'd get "value1".

Edit: PATH_FLDR_CONFIG points to the file itself.

Here's the code:

int length, i = 0;
    int inotify;
    char buffer[EVENT_BUF_LEN];

    if((inotify = inotify_init())<0){
        pthread_exit(NULL);
    }

    inotify_add_watch( inotify, PATH_FLDR_CONFIG , IN_MODIFY );

    while (true){
        i=0;
        length = read( inotify, buffer, EVENT_BUF_LEN );
        if (length<0) continue;

        while ( i < length ) {
            read( inotify, buffer, EVENT_BUF_LEN );
            struct inotify_event *event = ( struct inotify_event * ) &buffer[ i ];
            if ( event->mask & IN_MODIFY ) {
                    readConfigFile();
                }
            i += EVENT_SIZE + event->len;
          }

    }

Inside the readConfigFile() I do a configCreate + various reads;

t_config *config_create(char *path) {
    t_config *config = malloc(sizeof(t_config));

    config->path = strdup(path);
    config->properties = dictionary_create();

    struct stat stat_file;
    stat(path, &stat_file);
    FILE* file = NULL;

    file = fopen(path, "r");

    if (file != NULL) {
        char* buffer = calloc(1, stat_file.st_size + 1);
        fread(buffer, stat_file.st_size, 1, file);

        char** lines = string_split(buffer, "\n");

        void add_cofiguration(char *line) {
            if (!string_starts_with(line, "#")) {
                char** keyAndValue = string_split(line, "=");
                dictionary_put(config->properties, keyAndValue[0], keyAndValue[1]);
                free(keyAndValue[0]);
                free(keyAndValue);
            }
        }
        string_iterate_lines(lines, add_cofiguration);
        string_iterate_lines(lines, (void*) free);

        free(lines);
        free(buffer);
        fclose(file);
    }

    return config;
}

char *config_get_string_value(t_config *self, char *key) {
    return dictionary_get(self->properties, key);
}
役に立ちましたか?

解決

I am not certain but I think it is worth checking if your MODIFY notification is happening on your config file or on another file.

Many editors write changes to a file by first writing a temporary file. For example, if your file was named config.txt it might be written by writing .config.txt.new#1234 and then rename .config.txt.new#1234 to config.txt

Since inotify is on a directory it might be seeing the creation and modification of the temporary file, trigger a notification and your program reads the configuration before it can be replaced by the new file.

Another possible problem is that MODIFY event happens as soon as write() is called on the file. If the file is being written in several write calls, your program might open and read the configuration file before it is completely written. From your example, the configuration dictionary might contain the old values if they were not overwritten by a new value.

Instead of the MODIFY event, try using CLOSE_WRITE instead.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top