Lock file in unix(Solaris)

29.05.2018 10:45:22 Просмотров 28 Источник

Вопрос следующий: в man-е Solaris написано, что захват файлов наследуется при exec, однако, когда я захватываю файл на запись, а затем вызываю execlp(...) — открываю файл в редакторе. Затем я создаю новую сессию и запускаю ту же программу, по идее процесс должен остановиться в ожидании из-за флага F_SETLKW в fcntl(), но он также открывает редактор... В чем может быть дело?

#include <sys/types.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>

#define editor "nano"

int main(int argc, char *argv[]) {
    struct flock lock;
    int fd;

    if ((fd = open(argv[1], O_RDWR)) == -1) {
            perror("Cannot open file");
            exit(EXIT_FAILURE);
    }
    lock.l_type = F_WRLCK;
    lock.l_whence = SEEK_SET;
    lock.l_start = 0;
    lock.l_len = 0;

    if (fcntl(fd, F_SETLKW, &lock) == -1) {
            perror("fcntl failed");
            exit(EXIT_FAILURE);
    }

    execlp(editor, editor, argv[1], NULL);
    perror("exec is not working");
    exit(EXIT_FAILURE);

}
У вопроса есть решение - Посмотреть?

https://ru.stackoverflow.com/questions/834835/lock-file-in-unixsolaris#comment1336688_834835
@VTT, неинициализированы только выходные поля и, очевидно, проблему это не решает... ЗЫ: на linux'е тоже самое...
https://ru.stackoverflow.com/questions/834835/lock-file-in-unixsolaris#comment1336761_834835
Надо бы посмотреть в таблице файлов в /proc с чем связан этот fd после переключения на nano (может он закрывает дескрипторы и открывая файлы по новой их использует?)
https://ru.stackoverflow.com/questions/834835/lock-file-in-unixsolaris#comment1337693_834835
@user276153, и правда, похоже проблема в том, что редактор открывает тот же самый файл ещё раз: если передать ему другой файл, то всё работает как и ожидалось...

Ответы - Lock file in unix(Solaris) / Lock file in unix(Solaris)

Является ответом!
Fat-Zer

30.05.2018 06:37:50

man 2 fcntl (Solaris)

All locks associated with a file for a given process are removed when a file descriptor for that file is closed by that process or the process holding that file descriptor terminates

В linux этот момент расписан более подробно:

man 2 fcntl (Linux [man-pages-ru])

  • Если процесс закрывает любой файловый дескриптор, ссылающийся на файл, то освобождаются все блокировки процесса для этого файла, независимо от файлового дескриптора(ов), на который получена блокировка. Это плохо: это означает, что процесс может потерять свои блокировки на файл, такой как /etc/passwd или /etc/mtab, когда какой-либо причине библиотечная функция решает их открыть, прочитать и закрыть.

В данном случае происходит следующее: nano открывает тот же файл, на который удерживается блокировка (на другом дескрипторе), читает его и закрывает. В момент закрытия блокировка теряется, как и описано выше.

https://ru.stackoverflow.com/questions/834835/lock-file-in-unixsolaris/835547#comment1337829_835547
в том то и дело, что файл не закрывается, прочтите внимательно вопрос. В программе ставится блокировка с помощью fcntl, выполняется exec(nano..), процесс не завершается, затем в новой сессии запускается эта же программа, и тут-то процесс должен перейти в ожидание, т.к. блокировка уже стоит....
https://ru.stackoverflow.com/questions/834835/lock-file-in-unixsolaris/835547#comment1337949_835547
@user276153, тот же самый файл (argv[1]) передаётся в аргументах exec()'а в nano, после чего nano уже сам делает open()read()→**close()**. Вот этот самый close(), хотя он и работает с другим fd на тот же файл, и убивает блокировку.
https://ru.stackoverflow.com/questions/834835/lock-file-in-unixsolaris/835547#comment1338047_835547
Круто! А я-то всегда недоумевал, почему для локинга используют отдельный файл
https://ru.stackoverflow.com/questions/834835/lock-file-in-unixsolaris/835547#comment1338104_835547
@avp, но как тогда открыть файл и при этом не потерять блокировку, чем поможет отдельный файл?
https://ru.stackoverflow.com/questions/834835/lock-file-in-unixsolaris/835547#comment1338114_835547
@user276153, с блокировкой на другом файле close () на редактируемом не будет интерферировать с оной... ЗЫ: в соляре, на сколько я понимаю, других блокировок нет? flock () — это просто обёртка к fcntl()?
https://ru.stackoverflow.com/questions/834835/lock-file-in-unixsolaris/835547#comment1338125_835547
@Fat-Zer, других нет блокировок, на самом деле, не понятно, зачем так сделали. Сейчас пробую с link-ами что-нибудь сообразить...
https://ru.stackoverflow.com/questions/834835/lock-file-in-unixsolaris/835547#comment1338522_835547
@Fat-Zer обсолютно прав, блокировку можно использовать внутри программы на одном и том же открытом файловом дескрипторе, тогда это работает. Например в мультитредовом исполнении, чтобы ограничить запись/чтение файла из разных тредов. На уровне системы и разных приложений это использовать не рекомендуется.
https://ru.stackoverflow.com/questions/834835/lock-file-in-unixsolaris/835547#comment1338912_835547
@user276153, в общем-то Fat-Zer уже объяснил. Ну, например, создайте каталог /tmp/my-nano-locks/ и в нем делаете файлы с именем, сделанным из inode и devno того файла, что передаете nano (на самом деле тут будет довольно много мороки с удалением таких старых файлов) и делаете лок на этот файл. Я думаю, такая схема будет работать
https://ru.stackoverflow.com/questions/834835/lock-file-in-unixsolaris/835547#comment1338918_835547
@user276153, вы удивляетесь почему так сделали? Хороший вопрос. Видимо потому, что id владельца лока хранится в общей таблице открытых файлов, а там уже нет связи с fd в процессе, через который лок был получен. Поэтому любой close этого файла владельцем лока убивает лок. Видимо исправление такого поведение тянет за собой слишком много переделок, ухудшает производительность и т.п.
Закрыть X