Читать файл заблокирован для записи - PullRequest
1 голос
/ 21 февраля 2020

Я использую блокировку файлов как средство предотвращения нескольких запусков моего приложения:

FileLock lock = fc.tryLock();
if (lock == null) {
    System.out.println("Error: The process is already running.");
}

Пока все хорошо. Теперь я хотел бы написать еще один процесс, который сможет убить первый. Я хотел бы записать текущий PID в файл блокировки. Второй процесс подтвердит, что блокировка здесь (то есть процесс запущен), прочитает файл и уничтожит PID. Проверка блокировки перед чтением является обязательной, поскольку ОС может перезапускать PID: основной процесс может быть остановлен, а его PID повторно использован другим процессом. Проблема с чтением файла невозможна из-за блокировки (хотя я думал, что блокировка только помешает записи ...)

Вот упрощенный код:

public class TestLock {

    public static void main(String[] args) throws Exception {
        if (args.length == 1 && "kill".equals(args[0])) {
            kill();
        } else {
            run();
        }
    }

    private static void run() throws Exception {
        File file = new File("test.lock");
        try (FileOutputStream fos = new FileOutputStream(file)) {
            FileLock lock = fos.getChannel().tryLock();
            if (lock == null) {
                System.err.println("Error: The process is already running.");
            } else {
                int pid = Integer.parseInt(ManagementFactory.getRuntimeMXBean().getName().split("@")[0]);
                System.out.println("Process is launched with PID = " + pid);
                fos.write(String.valueOf(pid).getBytes("UTF-8"));
                while(true) {
                    Thread.sleep(3000);
                    System.out.println("App is running");
                }
            }
        }
    }

    private static void kill() throws Exception {
        File file = new File("test.lock");
        if (!file.exists()) {
            System.err.println("Error: The process is not running.");
            return;
        }
        try (FileChannel fc = FileChannel.open(file.toPath(), StandardOpenOption.READ)) {
            FileLock lock = fc.tryLock(0L, Long.MAX_VALUE, true);
            if (lock == null) {
                ByteBuffer bb = ByteBuffer.allocate(20);
                fc.read(bb);
                String pid = new String(bb.array(), "UTF-8").trim();
                System.out.println(pid);
                // Kill the process
            } else {
                System.err.println("Error: The process is not running.");
            }
        }
    }
}

Если я запускаю приложение дважды без аргумента второй экземпляр отображает «Ошибка: процесс уже запущен». Если я пытаюсь завершить процесс, пока он не запущен, появляется сообщение «Ошибка: процесс не запущен». Но если я пытаюсь завершить работающий процесс, я получаю IOException «Процесс не может получить доступ к файлу, потому что другой процесс заблокировал часть файла»

Просмотр в других потоках, что блокировки будут только рекомендательными (не действительно блокировка, если не проверено, если я правильно понял), я попытался снять проверку блокировки и использовать простой FileReader в методе kill, но я получаю ту же ошибку. (и в любом случае, я бы предпочел этого не делать из-за повторного использования PID, как указано ранее)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...