2015-10-16 2 views
2

Я реализую механизм взаимного исключения, основанный на блокировке файлов. Другие экземпляры моего скрипта знают, что они не должны запускаться, когда они поступают через определенный файл, который заблокирован.Как удалить заблокированный (стадо) файл без условия гонки: до или после освобождения блокировки?

Для этого я создал и заблокировал файл, используя fcntl.flock. Когда я освобождаю блокировку, я также хочу очистить файл, чтобы он не сидел там, указав старый pid, когда процесс не запущен.

Мой вопрос в том, когда и как следует очищать файл, особенно в какой момент я могу его удалить. В основном я вижу два варианта:

  • обрезать и удалить файл до снятия блокировки
  • обрезать и удалить файл после снятия блокировки

Из моего понимания, каждый из которых раскрывает мое приложение в несколько разных условиях гонки. Что такое лучшая практика, что я пропустил?

Вот (чрезмерно упрощенный) Пример:

import fcntl 
import os 
import sys 
import time 

# open file for read/write, create if necessary 
with open('my_lock_file.pid', 'a+') as f: 
    # acquire lock, raises exception if lock is hold by another process 
    try: 
     fcntl.flock(f, fcntl.LOCK_EX | fcntl.LOCK_NB) 
    except IOError: 
     print 'other process running:', f.readline() 
     sys.exit() 

    try: 
     # do something 
     f.write('%d\n' % os.getpid()) 
     f.flush() 
     # more stuff here ... 
     time.sleep(5) 
    finally: 
     # clean up here? 
     # release lock 
     fcntl.flock(f, fcntl.LOCK_UN) 
     # clean up here? 
# clean up here? 
+1

Также очень актуальной информации: HTTP: // stacko verflow.com/q/17708885/1025391 – moooeeeep

ответ

1

Я нашел этот родственный вопрос дать несколько советов о том, как справиться с этим делом:

Он также дал мне понять другое возможное состояние гонки, которое возникает, когда другой процесс удаляет файл сразу после его открытия с помощью cur процесс аренды. Это приведет к тому, что текущий процесс заблокирует файл, который больше не будет найден в файловой системе и, таким образом, не сможет заблокировать следующий процесс, который будет создавать его заново.

Там я нашел предложение использовать флаг открытия O_EXCL для создания атомного эксклюзивного файла, который открывается через функцию os.open() для операций с файлами низкого уровня. тогда я осуществил следующий пример соответственно:

import os 
import sys 
import time 

# acquire: open file for write, create if possible, exclusive access guaranteed 
fname = 'my_lock_file.pid' 
try: 
    fd = os.open(fname, os.O_CREAT|os.O_WRONLY|os.O_EXCL) 
except OSError: 
    # failed to open, another process is running 
    with open(fname) as f: 
     print "other process running:", f.readline() 
     sys.exit() 

try: 
    os.write(fd, '%d\n' % os.getpid()) 
    os.fsync(fd) 
    # do something 
    time.sleep(5) 
finally: 
    os.close(fd) 
    # release: delete file 
    os.remove(fname) 

После реализации этого, я узнал, что это точно такой же подход lockfile модуль использует для своих Pid файлов.

Для справки:

+0

Если скрипт выходит из строя во время шага «сделать что-то», файл блокировки не будет удален. Все будущие попытки запуска сценария будут печатать сообщение «другой процесс», потому что «os.O_EXCL» вызывает ошибку, если файл уже существует.По этой причине другие методы, такие как блокировка процесса, предоставленная в пакете [крепления] (http://fasteners.readthedocs.io/en/latest/api/process_lock.html), не очищают файл блокировки. Если вы хотите, чтобы файл блокировки был удален, я думаю, вам нужно установить файл после приобретения блокировки, как было предложено в ответе, с которым вы связались. –

 Смежные вопросы

  • Нет связанных вопросов^_^