Перейти к содержимому

Как отключить Ctrl-Alt-C

Fingercomp

1 028 просмотров

TL;DR: require("process").info().data.signal = function() end.

 

С версии OpenOS 1.7.3 интеррапты работают так:

local interrupting = uptime() - lastInterrupt > 1 and keyboard.isControlDown() and keyboard.isKeyDown(keyboard.keys.c)
if interrupting then
  lastInterrupt = uptime()
  if keyboard.isAltDown() then
    require("process").info().data.signal("interrupted", 0)
    return
  end
  event.push("interrupted", lastInterrupt)
end

Это отрывок из /lib/event.lua. Он говорит, что если зажать Ctrl, Alt и C, то вызовется некоторая функция: require("process").info().data.signal.

 

Программы в OpenOS запускаются в процессах. У каждого процесса есть свой главный поток (о них я писал где-то там), своё окружение. Каждый процесс следит за тем, какие файлы открыты, чтобы их закрыть при завершении процесса, жонглирует событиями и занимается сложной логикой. А ещё у каждого процесса есть свои данные. Эти данные для текущего процесса как раз возвращает process.info().data.

 

У процессов есть иерархия. Корневой процесс — это тот, в котором запускается /init.lua. В нём устанавливается переменная signal:

-- /boot/01_process.lua
local init_thread = _coroutine.running()
process.list[init_thread] = {
  path = "/init.lua",
  command = "init",
  env = _ENV,
  data =
  {
    vars={},
    handles={},
    io={}, --init will populate this
    coroutine_handler = _coroutine,
    signal = error -- ①
  },
  instances = setmetatable({}, {__mode="v"})
}

 

Другие программы запускаются в дочерних процессах. Они наследуют данные родительского процесса. Поэтому process.info().data.signal, обработчик жёсткого интеррапта, по умолчанию возвращает функцию error. Но данные можно переопределить. Как видно из кода /lib/event.lua, нам достаточно, чтобы новый обработчик не вызывал error.

require("process").info().data.signal = function(msg, level)
  print("You've pressed Ctrl-Alt-C!")
end

Это будет работать для всех потоков внутри текущего процесса, а также для других, запущенных в нём.

 

Стоит отметить, что потоки знают, к какому процессу они прицеплены, и этот процесс можно менять на другой. thread:detach() — просто лёгкий способ сменить процесс, в котором работает поток, на корневой. А там process.info().data.signal — это функция error. Поэтому после Ctrl-Alt-C поток всё равно получит ошибку и, если она не поймана, завершится. А программа продолжит работать. Поэтому, чтобы быть совсем спокойным, можно отключить Ctrl-Alt-C глобально:

local process = require("process")

local p = process.findProcess()

while p.parent do
  p = p.parent
end

p.data.signal = function() end

Хотя я бы, конечно, не советовал так делать. Очень неудобно потом останавливать другие программы: приходится перезагружать компьютер.

  • Нравится 5


0 комментариев


Рекомендуемые комментарии

Нет комментариев для отображения

Гость
Добавить комментарий...

×   Вы вставили отформатированное содержимое.   Удалить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отобразить как ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...