PrepareForShutdown

Вопросы программирования на Free Pascal, использования компилятора и утилит.

Модератор: Модераторы

PrepareForShutdown

Сообщение Alexander » 18.09.2023 15:04:27

В завершении работы системы бывает нужно корректно завершить программу, сохранив данные.

Для этого в Линуксе есть возможность через dbus принять сигнал PrepareForShutdown c true, а затем с false. Его посылает systemd. Также в документации указана необходимость применения ингибитора для того, чтобы приостановить выключение, пока сигнал обрабатывается. Это в общих чертах.

Кроме того, такая возможность была бы нужна и в RTL самого Паскаля, чтобы работала секция finalization.
Трудно сказать как это реализовать не слишком громоздко, но это было бы полезно.

Отсюда вопрос: нет ли готовой реализации этого на Паскале ? Сходу не нашёл. Или это только предстоит сделать.

Декларации dbus есть в FPC и MSEgui, но реализаций PrepareForShutdown не видно.
Аватара пользователя
Alexander
энтузиаст
 
Сообщения: 697
Зарегистрирован: 18.12.2005 19:10:00
Откуда: оттуда

Re: PrepareForShutdown

Сообщение RRYTY » 18.09.2023 17:58:33

В линуксе при подготовке к выключению всем приложениям посылают сигнал SIGQUIT (его можно послать ручками командой kill -s 3). Корректная программа его корректно понимает. Кто не понимает - убивается за тупость. Приостанавливать процесс выключения могут лишь программы, запущенные специальным образом и с особыми правами.
RRYTY
постоялец
 
Сообщения: 187
Зарегистрирован: 25.12.2021 10:00:32

Re: PrepareForShutdown

Сообщение Alexander » 18.09.2023 18:50:00

> Приостанавливать процесс выключения могут лишь

Вот чтобы не так. Это ошибочный в принципе путь. Именно обычная программа должна сохранять данные корректно. Об этом и речь.
Остальное глупости. По этой логике обычная программа, оставшаяся работать при выключении системы потеряет данные. Этого не должно быть никак.

https://www.freedesktop.org/software/sy ... ml#Signals

Signals

Whenever the inhibition state or idle hint changes, PropertyChanged signals are sent out to which clients can subscribe.

The SessionNew, SessionRemoved, UserNew, UserRemoved, SeatNew, and SeatRemoved signals are sent each time a session is created or removed, a user logs in or out, or a seat is added or removed. They each contain the ID of the object plus the object path.

The PrepareForShutdown() and PrepareForSleep() signals are sent right before (with the argument "true") or after (with the argument "false") the system goes down for reboot/poweroff and suspend/hibernate, respectively. This may be used by applications to save data on disk, release memory, or do other jobs that should be done shortly before shutdown/sleep, in conjunction with delay inhibitor locks. After completion of this work they should release their inhibition locks in order to not delay the operation any further. For more information see Inhibitor Locks.
Аватара пользователя
Alexander
энтузиаст
 
Сообщения: 697
Зарегистрирован: 18.12.2005 19:10:00
Откуда: оттуда

Re: PrepareForShutdown

Сообщение RRYTY » 18.09.2023 21:41:02

Нет разницы межды завершением работы программы по желанию пользователя или по сигналу системы. Исключение только для системных и серверных приложений. Их создание - отдельная тема и пользоваться Free Pascal Compiler для этого будет стратегической ошибкой. Это все, что хотел донести.
RRYTY
постоялец
 
Сообщения: 187
Зарегистрирован: 25.12.2021 10:00:32

Re: PrepareForShutdown

Сообщение Alexander » 18.09.2023 22:34:31

Это всё полностью неверно. До тех пор, пока пользовательские программы не завершат корректно свою работу, система не может быть остановлена - они должны блокировать завершение работы системы на время сохранения своих данных. И есть специальный механизм для этого, который я и предлагаю наконец задействовать. Никаких особенных "серверных" или "системных" программ не бывает. cat - это системная, серверная или пользовательская программа ? Она, очевидно, и то и другое и третье. Это добавляет непонимания вопроса о выключении системы.
Паскаль очень устроен для этого, даже специально, чего нет в Си. Только в Паскале есть для этого специальная секция finalization, в других языках её вообще нет.
Аватара пользователя
Alexander
энтузиаст
 
Сообщения: 697
Зарегистрирован: 18.12.2005 19:10:00
Откуда: оттуда

Re: PrepareForShutdown

Сообщение RRYTY » 18.09.2023 23:31:00

Alexander писал(а):До тех пор, пока пользовательские программы не завершат корректно свою работу, система не может быть остановлена - они должны блокировать завершение работы системы на время сохранения своих данных.


Программа пользователя имеет приоритет над системой. Ужас. Написал тупой луп и завесился наглухо. Ах-ах, нужно подождать корректного завершения. :-D

Alexander писал(а):cat - это системная, серверная или пользовательская программа ? Она, очевидно, и то и другое и третье.


Пользовательская программа. Всегда один пользователь, запускается в контексте пользователя, может быть прервана в любой момент как пользователем (предусмотрено разработчиком), так и системой (вне зависимости от желания разработчика). Так как разработчик адекватный, то не придется ждать завершения "cat /dev/zero" чтобы выключить систему. При получении синала SIGQUIT (неважно откуда) она корректно прекратит работу.

Finalization использовать можно и нужно. Систему тормозить, пока finalization не выполнится, нельзя и не нужно. Это обязательно для пользовательской программы. Нормальная система не позволит какой-то пользовательской фигне где бы то ни было себя тормозить. И уж, тем более, блокировать. }:-)
RRYTY
постоялец
 
Сообщения: 187
Зарегистрирован: 25.12.2021 10:00:32

Re: PrepareForShutdown

Сообщение Alexander » 19.09.2023 07:40:43

> Программа пользователя имеет приоритет над системой. Ужас.

Однозначно так. И не иначе. А ужас противоположное.

В Юникс и Линукс программы универсальны: они и системны и пользовательские. Нет границы между ними -- на то и универсальная система. Это принципиальное, краеугольное отличие универсальной системы от системы с неуниверсальными программами. Как пользователь, так и системные скрипты используют cat. По этому и то и другое. Из таких утилит и собрана система. Система ГНУ даже своего ядра не имеет -- она состоит только из таких универсальных (системно-пользовательских) программ и не из чего больше. И это уже система. Ядро -- это отдельная тема, но и оно создано использованием этих программ и никаких больше. Это понятно из устройства и из названия системы.

К корректному завершению работы системы относится только блокировка специальным способом выключения на время сохранения программой данных. Иное поведение приводит к аварийному завершению работы системы с потерей данных. Это хорошо известно, понятно, описано и имеет два таких устойчивых названия.
Прерывание сохранения суперпользователем возможно, но это называется форсированным, принудительным выключением с потерей данных и это не штатный, экстренный случай. При корректном устройстве это никогда не приведёт к зависанию, а только такое и предполагается.
"cat /dev/zero" это не тот случай, когда cat заблокирует выключение системы. Зачем это cat'у нужно ? Это было бы бессмысленным действием, а cat осмысленная программа с определённым назначением. Откуда это ? Программа в таком случае блокирует выключение на небесконечное значение, а на специально минимизированную паузу, необходимую для сохранения конечных по размеру данных. Иное невозможно.

Пользовательская программа не "фигня", а то ради чего у пользователя и есть компьютер. Это главное, а не второстепенное. Нельзя же так путать.
Пользователь использует программу, программа использует операционную систему, операционная система использует "железо". Вроде бы всё однозначно и очевидно в этой связке. Как можно было предположить противоположное и настаивать на текущем аварийном положении дел в этом вопросе ?
Аватара пользователя
Alexander
энтузиаст
 
Сообщения: 697
Зарегистрирован: 18.12.2005 19:10:00
Откуда: оттуда

Re: PrepareForShutdown

Сообщение RRYTY » 19.09.2023 08:36:05

Ладно.
RRYTY
постоялец
 
Сообщения: 187
Зарегистрирован: 25.12.2021 10:00:32

Re: PrepareForShutdown

Сообщение Снег Север » 19.09.2023 09:30:54

Alexander напишите свою ОС под свои хотелки. А в существующих ОС никто вам не позволит блокировать выключение из-за криворукой реализации своей программы.
Аватара пользователя
Снег Север
долгожитель
 
Сообщения: 2995
Зарегистрирован: 27.11.2007 16:14:47

Re: PrepareForShutdown

Сообщение Alex2013 » 19.09.2023 10:50:28

Во первых любая система должна уметь ( и умеет) завершать работу безусловно или с ожиданием таймаута (это не совсем корректно но лучше чем "тупая остановка" ( как минимум корректно завешаются системные процессы "демонов/сервисов" и аппаратные интерфейсы (драйвера) на уровне ядра ) ).
Во вторых, чем обработчик onClose плох ? Насколько я примаю при стандартном выполнении Shutdown (или Logout ) в начал просто рассылается команда на стандартное закрытие всех программ прикладного уровня.
Alex2013
долгожитель
 
Сообщения: 2941
Зарегистрирован: 03.04.2013 11:59:44

Re: PrepareForShutdown

Сообщение alexs » 19.09.2023 15:55:33

Alexander
Вы говорите правильные вещи в том, что пользовтельские данные священны и их нельзя потерять.
Но из этого делаете не верный вывод что данные надо сохранять перед завершение работы программы.
Данные должны сохраняться по ходу работы пользователя.
Т.е. в программе во время работы не должно быть не сохранённых данных.
Аватара пользователя
alexs
долгожитель
 
Сообщения: 4053
Зарегистрирован: 15.05.2005 23:17:07
Откуда: г.Ставрополь

Re: PrepareForShutdown

Сообщение Alex2013 » 19.09.2023 16:46:45

alexs писал(а):Данные должны сохраняться по ходу работы пользователя.
Т.е. в программе во время работы не должно быть не сохранённых данных.

Это тоже неплохой метод но что делать если нужно именно возможность НЕ СОХРАНЯТЬ изменения ?
(Нет понятно что можно сделать некий временный файл и после возможного внезапного "Шута-И-Дуна", восстанавливать именно его но даже это иногда бывает ПОМЕХОЙ )
Alex2013
долгожитель
 
Сообщения: 2941
Зарегистрирован: 03.04.2013 11:59:44

Re: PrepareForShutdown

Сообщение alexs » 19.09.2023 17:44:27

А зечем их тогда вообще вводить? Если не сохранять?
Более правильно дать пользователю возможность отменить изменения.
А держать не сохранённые изменения - это плохо. Так можно додуматься и держать не подтверждённую транзакцию для записи :-)
Аватара пользователя
alexs
долгожитель
 
Сообщения: 4053
Зарегистрирован: 15.05.2005 23:17:07
Откуда: г.Ставрополь

Re: PrepareForShutdown

Сообщение v-t-l » 20.09.2023 12:19:54

Alexander писал(а):До тех пор, пока пользовательские программы не завершат корректно свою работу, система не может быть остановлена

Это вам виндовс надо.
v-t-l
энтузиаст
 
Сообщения: 728
Зарегистрирован: 13.05.2007 16:27:22
Откуда: Belarus

Re: PrepareForShutdown

Сообщение Alexander » 20.09.2023 20:50:31

> Это вам виндовс надо.

Туда я уже заглядывал и эту проблему давно успешно решал там старыми средствами. Но вот туда уже точно не надо. Не та система.
Вопрос был именно о Линукс и FreeePascal, а не Win + Delphi.

Именно здесь нужно решить эту задачу. И она здесь и современнее и мощнее, но и сложнее. Тем более, что разработчики FPC в упор не видят самой проблемы, а она есть.

Решается обработкой PrepareForShutdown. С применением https://www.freedesktop.org/wiki/Softwa ... d/inhibit/ :

Автоперевод:
Замки-ингибиторы

systemd 183 и новее включают логику, запрещающую завершение работы системы и переходы в спящий режим. Это реализовано как часть systemd-logind.daemon(8). Для этого существует несколько различных вариантов использования:

Приложение для записи компакт-дисков хочет гарантировать, что система не будет выключена или приостановлена во время процесса записи.
Менеджер пакетов хочет гарантировать, что система не будет выключена во время обновления пакета.
Офисный пакет хочет получать уведомления перед приостановкой системы, чтобы сохранить все данные на диск, и задерживать логику приостановки до тех пор, пока все данные не будут записаны.
Веб-браузер хочет получить уведомление перед переходом системы в спящий режим, чтобы освободить его кэш и минимизировать объем памяти, которую необходимо виртуализировать.
Инструмент блокировки экрана хочет активировать блокировку экрана непосредственно перед приостановкой и отложить приостановку до ее завершения.

Приложения, которые хотят использовать логику блокировки, должны использовать блокировку блокировки через API входа в систему D-Bus.

Можно использовать семь различных типов блокировок-ингибиторов или их комбинацию:

сон запрещает приостановку работы системы и переход в спящий режим, запрошенные (непривилегированными) пользователями
завершение работы запрещает высокоуровневое выключение системы и перезагрузку по запросу (непривилегированных) пользователей.
«idle» запрещает переход системы в режим ожидания, что может привести к автоматической приостановке или выключению системы в зависимости от конфигурации.
handle-power-key запрещает низкоуровневую (т. е. логин-внутреннюю) обработку аппаратного ключа питания системы, позволяя вместо этого (возможно, непривилегированному) внешнему коду обрабатывать событие.
Аналогичным образом, handle-suspend-key запрещает низкоуровневую обработку аппаратной клавиши приостановки системы.
Аналогичным образом, handle-hibernate-key запрещает низкоуровневую обработку аппаратного ключа гибернации системы.
Аналогичным образом, handle-lid-switch запрещает низкоуровневую обработку аппаратного переключателя крышки systemd.

Поддерживаются два различных режима блокировок:

блокировка полностью запрещает операции до тех пор, пока блокировка не будет снята. Если такая блокировка будет принята, операция завершится неудачно (но ее все же можно переопределить, если пользователь обладает необходимыми привилегиями).
Задержка запрещает операции только временно, либо до тех пор, пока блокировка не будет снята, либо до определенного периода времени. Параметр InhibitDelayMaxSec= в файле logind.conf(5) управляет таймаутом для этого. Это предназначено для использования приложениями, которым требуется синхронный способ выполнения действий перед приостановкой системы, но им не разрешено блокировать приостановку на неопределенный срок. Этот режим доступен только для блокировки сна и выключения.

Блокировки ингибитора выполняются с помощью вызова D-Bus Inhibit() объекта logind Manager:

Inhibit() — единственный API, необходимый для блокировки. Требуется четыре аргумента:

Что такое список типов блокировки, разделенных двоеточиями, т. е. выключение, спящий режим, режим ожидания, ручка-ключ-питание, ручка-ключ-приостановка, ручка-ключ-спящий режим, ручка-крышка-переключатель. Пример: «выключение: холостой ход»
Кто — удобочитаемая строка описания того, кто берет блокировку. Пример: «Программа обновления пакетов».
«Почему» — удобочитаемая строка с описанием причины блокировки. Пример: «Выполняется обновление пакета».
Режим — блокировка или задержка, см. выше. Пример: «блокировать».

Inhibit() возвращает одно значение — файловый дескриптор, инкапсулирующий блокировку. Как только файловый дескриптор закрывается (и все его дубликаты), блокировка автоматически снимается. Если клиент умирает во время блокировки, ядро автоматически закрывает дескриптор файла, и блокировка автоматически снимается. Принятая таким образом блокировка задержки должна быть снята как можно скорее при получении AcceptForShutdown(true) (см. ниже), но, конечно, только после выполнения действий, для которых приложение изначально хотело отложить операцию.

ListInhibitors() выводит список всех активных в данный момент блокировок-ингибиторов. Он возвращает массив структур, каждая из которых состоит из What, Who,Why, Mode, как указано выше, а также PID и UID процесса, запросившего блокировку.

Сигналы ПодготовкаForShutdown() и ПодготовкаForSleep() подаются, когда приостановка или завершение работы системы запрошена и вот-вот будет выполнена, а также после того, как приостановка/выключение была завершена (или не удалась). Сигналы содержат логический аргумент. Если True, было запрошено завершение работы/переход в спящий режим, и начинается фаза подготовки к нему, если False, операция завершилась (или завершилась неудачей). Если принимает значение True, это следует использовать как указание приложениям быстро выполнить операции, которые они хотели выполнить, перед приостановкой/завершением работы, а затем снять любую блокировку задержки. Если значение равно False, операция приостановки/выключения завершена успешно или неудачно (конечно, этот сигнал никогда не будет отправлен, если запрос на выключение был успешным). Сигнал с значением False обычно доставляется только после того, как система возвращается из режима ожидания, а также сигнал с значением True, например, когда изначально не была установлена блокировка задержки, и поэтому приостановка системы выполняется без какой-либо задержки. Сигнал с значением False обычно является сигналом, по которому приложения запрашивают новую блокировку задержки, чтобы быть синхронно уведомленными о следующем цикле приостановки/выключения. Обратите внимание, что просмотр «PrepareForShutdown(true)?/PrepareForSleep(true)» без блокировки задержки является грубым и не должен выполняться, поскольку любой код, который приложение может захотеть выполнить по этому сигналу, может фактически не завершиться до завершения цикла приостановки/выключения. казнен. Опять же: если вы смотрите «ПодготовкаForSuspend(true)», то вам действительно следовало сначала использовать блокировку задержки. На AcceptForShutdown(false) могут подписываться приложения, которые хотят получать уведомления о событиях возобновления работы системы. Обратите внимание, что это будет отправлено только для циклов приостановки/возобновления, выполняемых через вход в систему, т. е., как правило, только для циклов приостановки высокого уровня, вызванных пользователем, а не автоматических циклов приостановки низкого уровня, индуцируемых ядром, которые могут существовать на определенных устройствах с более агрессивной мощностью. управление.

Свойства BlockInhibited и DelayInhibited определяют, какие типы блокировок используются в данный момент. Эти поля представляют собой список, разделенный двоеточиями: выключение, спящий режим, режим ожидания, ручка-клавиша включения, ручка-клавиша приостановки, ручка-клавиша гибернации, ручка-крышка-переключатель. По сути, список представляет собой объединение полей «Что» всех активных в данный момент блокировок определенного режима.

InhibitDelayMaxUSec содержит значение тайм-аута задержки, настроенное в файле logind.conf(5).

Логические свойства PreparingForShutdown и PreparingForSleep являются истинными между двумя отправляемыми сигналами AcademicForShutdown() и PreparingForSleep(). Обратите внимание, что эти свойства не вызывают сигналы PropertyChanged.
Взятие блокирующих замков

Вот базовая схема для приложений, которым требуется блокировка блокировок, таких как менеджер пакетов или приложение для записи компакт-дисков:

Возьмите замок
Выполняйте свою работу, которую не хотите прерывать спящим режимом или выключением системы.
Отпустите замок

Пример псевдокода:

Взятие блокировки задержки

Вот базовая схема для приложений, которым требуется блокировка с задержкой, таких как веб-браузер или офисный пакет:

Открывая документ, используйте блокировку задержки.
Как только вы увидите AcceptForSleep(true), сохраните данные, а затем снимите блокировку.
Как только вы увидите «ПодготовкаForSleep(false»), снова включите блокировку задержки и продолжайте, как прежде.

Пример псевдокода:

Взятие замков с ключами

По умолчанию logind управляет клавишами питания и сна машины, а также переключателем крышки во всех состояниях. Это гарантирует, что это базовое поведение системы гарантированно будет работать при любых обстоятельствах, как на текстовых консолях, так и во всех графических средах. Однако некоторые DE могут захотеть самостоятельно обрабатывать эти клавиши, например, чтобы показать красивое диалоговое окно перед выполнением соответствующей операции или просто отключить действие при определенных условиях. Для этих случаев доступны блокировки типа «ручка-ключ-питание», «ручка-ключ-приостановка», «ручка-клавиша гибернации» и «ручка-крышка-выключатель». При использовании эти блокировки просто отключают низкоуровневую обработку ключей, они не влияют на приостановку/гибернацию/выключение системы, выполняемую с помощью других механизмов, кроме аппаратных клавиш (например, когда пользователь вводит «systemctl suspend» в оболочке). DE, намеревающийся самостоятельно обрабатывать эти ключи, должен просто снимать блокировки во время входа в систему и снимать их при выходе из системы; в качестве альтернативы может иметь смысл использовать эту блокировку только временно при определенных обстоятельствах (например, использовать блокировку переключателя крышки только тогда, когда подключен второй монитор, чтобы поддерживать обычную настройку, при которой люди закрывают свои ноутбуки, когда у них подключен большой экран) .

Эти блокировки нужно снимать в режиме «блок», «задержка» для них не поддерживается.

Если DE хочет, чтобы экран блокировки для возможного возобновления отображался на экране до того, как система перейдет в состояние ожидания, ему следует сделать это с помощью блока ингибитора задержки приостановки (см. выше).
Разное

Взлом блокировочных замков — привилегированная операция. В зависимости от действия org.freedesktop.login1.inhibit-block-shutdown, org.freedesktop.login1.inhibit-delay-shutdown, org.freedesktop.login1.inhibit-block-sleep, org.freedesktop.login1.inhibit-delay- сон, org.freedesktop.login1.inhibit-block-idle, org.freedesktop.login1.inhibit-handle-power-key, org.freedesktop.login1.inhibit-handle-suspend-key, org.freedesktop.login1.inhibit- handle-hibernate-key,org.freedesktop.login1.inhibit-handle-lid-switch. В целом следует предположить, что блокировки с задержкой получить легче, чем блокировки блокировки, просто потому, что их влияние гораздо минимальнее. Обратите внимание, что проверки политики для Inhibit() никогда не бывают интерактивными.

Замки-ингибиторы не следует использовать неправильно. Например, блокировка бездействующей блокировки без уважительной причины может привести к тому, что мобильные устройства никогда не будут автоматически приостанавливать работу. Это может быть весьма вредно для аккумулятора.

Если приложение обнаруживает, что блокировка отклонена, ему не следует считать это большой ошибкой и просто продолжать свою работу без защитной блокировки.

Инструмент systemd-inhibit(1) можно использовать для снятия блокировок или получения списка активных блокировок из командной строки.

Обратите внимание, что gnome-session также предоставляет API-интерфейс ингибитора, который очень похож на API-интерфейс systemd. Внутренние блокировки, установленные на интерфейсе gnome-session, будут перенаправлены на вход в систему, поэтому поддерживаются оба API. Хотя оба предлагают схожие функциональные возможности, они в некоторых отношениях различаются. По очевидным причинам gnome-session может предлагать блокировки выхода из системы и блокировки блокировки заставки, которых нет в Logind. API OTOH входа в систему поддерживает блокировки с задержкой в дополнение к блокировкам блоков, таким как GNOME. Кроме того, logind доступен для компонентов системы и централизует блокировки всех пользователей, а не только конкретного. В общем: если есть сомнения, вероятно, рекомендуется придерживаться блокировок GNOME, если только нет веской причины напрямую использовать API входа в систему. Однако, когда необходимо перечислить блокировки, лучше использовать API-интерфейсы входа в систему, поскольку они также включают блокировки, выполняемые системными службами и другими пользователями.
Аватара пользователя
Alexander
энтузиаст
 
Сообщения: 697
Зарегистрирован: 18.12.2005 19:10:00
Откуда: оттуда

След.

Вернуться в Free Pascal Compiler

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 14

Рейтинг@Mail.ru