View Issue Details

IDProjectCategoryView StatusLast Update
0003920PluginsLuaMacro / Macro Browserpublic2021-12-09 18:54
Reporterheilong Assigned To 
PrioritynormalSeveritymajorReproducibilitysometimes
Status closedResolutionnot fixable 
Platformx64OSWindowsOS Version10
Product Version3.0 
Summary0003920: Под нагрузкой, стрелки вверх-вниз (и др.) генерируют символы на ком строке
DescriptionПри нагрузке процессора, нажатие разных клавиш в Фаре приводит к появлению неких key-кодов на командной строке. Например, при нажатии стрелок вверх-вниз вместо перемещения по списку файлов, на ком строке появляются [A или [B.
Данная проблема усугубляется, если Far работает под ConEmu, но и без ConEmu у меня также получилось это воспроизвести.
Steps To Reproduce- Запустить Far, желательно из-под ConEmu (воспроизвести легче)
- Загрузить чем-то процессор, например я использовал онлайн стресс тест отсюда
- В Far, быстро понажимать (или нажать и держать) стрелки вверх-вниз

Far либо реагирует медленно на нажатия стрелок, либо на ком строке появляются символы [A / [B.
Additional Information- Также воспроизводится на прочих других клавишах.
- На моём Windows 7 (x64) ноутбуке эта проблема ни разу не замечалась
- На 3х разных Windows 10 (x64) ноутбуках (та же модель, на год новее моего Win 7 ноутбука) проблема воспроизводится постоянно
- Проблему я заметил год или два назад, когда впервые поставил Windows 10. Far и прочая конфигурация была скопирована с моего Windows 7 ноутбука. Периодически обновляюсь на nightly версию Far-а, на данный момент 3.0.0.5927.
- Приложен скриншот standalone Far-а (без ConEmu) с вылезшим (при нажатии на стрелку вверх) на ком строке кодом [A
TagsNo tags attached.

Activities

heilong

2021-12-04 10:23

reporter  

DrKnS

2021-12-04 16:33

administrator   bugnote:0017262

Conemu уже был замечен в подобном, в несколько ином контексте.

Приложен скриншот standalone Far-а (без ConEmu)
Я надеюсь, вы проверяете совсем без conemu, в т.ч. и без его плагинов, а не просто запуская far.exe из той же папки напрямую?

heilong

2021-12-04 19:37

reporter   bugnote:0017267

Был плагин conemu. Скопировал установку Far-а в отдельную директорию, удалил оттуда плагин conemu. Баг воспроизводится.

heilong

2021-12-04 20:23

reporter   bugnote:0017269

Conemu уже был замечен в подобном, в несколько ином контексте.

DrKnS

Прочтение этой темы навело на мысль попробовать, а не влияют ли на проблему мои Lua-скрипты?
Взял nightly archive Far, разархивировал в отдельную директорию, все дальнейшие тесты проводил с этим фаром, без ConEmu. Методом исключения обнаружилось, что проблема вызывается одним конкретным скриптом Panel.ChangeDir.lua (приаттачил). Если закомментировать строчку os.execute, проблема исчезает.

Отключил этот скрипт в обычной установке Far, которой пользуюсь из-под ConEmu. Проблема также исчезла.

Скрипт писал 5 лет назад, в коммите (скрипты у меня в git репозитории) написано "Panel.ChangeDir: On Far start, make sure both panels are visible and none of the panels are showing the user dir". Насколько я помню, при запуске Far (кажется, именно из-под ConEmu, но точно не помню) одна из панелей показывала home директорию юзера, а мне это не нравилось.
Panel.ChangeDir.lua (4,076 bytes)   
-- Timer poll interval in milliseconds.
local POLL_INTERVAL = 5000
-- Timer boost on input event interval in milliseconds.
local BOOST_INTERVAL = 500

local SQLITE = 'C:\\cygwin\\bin\\setsid.exe C:\\cygwin\\bin\\sqlite3.exe' -- Run sqlite3 in background (returns immediately, best performance).
--local SQLITE = 'C:\\cygwin\\bin\\sqlite3.exe' -- Run sqlite3 directly (blocks execution until transaction has finished).
local LOCALCONFIG_DB = win.GetEnv('FARPROFILE') .. '\\localconfig.db'

--local dbg = require "dbgprint".filter("FAR:"," ")
--local inspect = require "inspect"

local function CommitPanelState()
--	dbg.print('commit')
	local leftPanel = APanel.Left and APanel or PPanel
	local rightPanel = APanel.Left and PPanel or APanel
	local sql = "BEGIN TRANSACTION; DELETE FROM 'general_config'; " ..
		"INSERT INTO 'general_config' VALUES('Panel.Left','CurFile','" .. leftPanel.Current:gsub("'", "''") .. "'); " ..
		"INSERT INTO 'general_config' VALUES('Panel.Left','Folder','" .. leftPanel.Path0:gsub("'", "''") .. "'); " ..
		"INSERT INTO 'general_config' VALUES('Panel.Right','CurFile','" .. rightPanel.Current:gsub("'", "''") .. "'); " ..
		"INSERT INTO 'general_config' VALUES('Panel.Right','Folder','" .. rightPanel.Path0:gsub("'", "''") .. "'); " ..
		"INSERT INTO 'general_config' VALUES('Panel','LeftFocus'," .. (APanel.Left and 1 or 0) .. "); " ..
		"COMMIT;"
--	os.execute(SQLITE .. ' "' .. LOCALCONFIG_DB .. '" "' .. sql .. '"')
end

local lastActiveLeft = APanel.Left
local lastLeftPath = APanel.Left and APanel.Path0 or PPanel.Path0
local lastLeftCurrent = APanel.Left and APanel.Current or PPanel.Current
local lastRightPath = APanel.Left and PPanel.Path0 or APanel.Path0
local lastRightCurrent = APanel.Left and PPanel.Current or APanel.Current

local function UpdatePanelState()
	local leftPanel = APanel.Left and APanel or PPanel
	local rightPanel = APanel.Left and PPanel or APanel
	local modified = false
	
	if APanel.Left ~= lastActiveLeft then
		lastActiveLeft = APanel.Left
		modified = true
	end
	if (leftPanel.Type == 0) and ((leftPanel.Path0 ~= lastLeftPath) or (leftPanel.Current ~= lastLeftCurrent)) then
		lastLeftPath = leftPanel.Path0
		lastLeftCurrent = leftPanel.Current
		modified = true
	end
	if (rightPanel.Type == 0) and ((rightPanel.Path0 ~= lastRightPath) or (rightPanel.Current ~= lastRightCurrent)) then
		lastRightPath = rightPanel.Path0
		lastRightCurrent = rightPanel.Current
		modified = true
	end
	
	if modified then
		CommitPanelState()
	end
end

local timer = far.Timer(POLL_INTERVAL, function(timer)
	timer.Enabled = false
	UpdatePanelState()
	timer.Interval = POLL_INTERVAL
	timer.Enabled = true
end)

Event { description="PanelChangeDir: Clean up timer on exit"; group="ExitFAR";
	uid="351F4780-2799-47BF-984A-EB429E8B431E";
	action=function()
		timer:Close()
	end;
}

Event { description="PanelChangeDir: Listen to input events"; group="ConsoleInput";
	action=function(Rec)
		if ((Rec.EventType == far.Flags.KEY_EVENT) and (Rec.VirtualKeyCode ~= 0)) or
			 ((Rec.EventType == far.Flags.MOUSE_EVENT) and (Rec.EventFlags ~= far.Flags.MOUSE_MOVED)) then
			timer.Interval = BOOST_INTERVAL
		end
	end;
}

local function InitPanelState()
	-- Make sure both panels are visible.
	if (not APanel.Visible) and (not PPanel.Visible) then
		Keys('CtrlO')
	elseif not PPanel.Visible then
		Keys('CtrlP')
	end
	
	-- If one or both panels have the user's home directory open, go to last history item or two last history items respectively.
	local home = win.GetEnv('HOMEDRIVE') .. win.GetEnv('HOMEPATH')
	if (APanel.Path == home) or (PPanel.Path == home) then
		Keys('AltF12')
		local itemPos = Menu.Select(home)
		if itemPos > 0 then
			Keys('ShiftDel End')
		end
		if APanel.Path == home then
			panel.SetPanelDirectory(nil, 1, Menu.Value or 'C:\\')
			Keys('Up')
		end
		if PPanel.Path == home then
			panel.SetPanelDirectory(nil, 0, Menu.Value or 'C:\\')
		end
		Keys('Esc')
	end
end

Macro { description="PanelChangeDir: Init panels on start";
	area="Shell"; key="auto"; flags="RunAfterFARStart";
	action = InitPanelState;
}
Panel.ChangeDir.lua (4,076 bytes)   

heilong

2021-12-04 20:32

reporter   bugnote:0017270

Похоже, что дело именно в os.execute, потому что проблема также воспроизводится, если сразу при старте Far зажать стрелку вверх или вниз, и при этом есть скрипт Alias.lua (в аттаче), который запускает doskey с помощью os.execute.

С точки зрения workaround-ов - полагаю, что мой 5-летней давности Panel.ChangeDir уже не нужен, я его отключил, и не вижу никаких изменений в худшую сторону - home директория юзера не открывается при старте нового Far (ConEmu). Alias, как я вижу, на форуме уже есть в обновлённой версии, которая, похоже, уже не использует os.execute и вообще doskey.

Но всё же могу предположить, что некая проблема существует, os.execute-ом разные скрипты могут пользоваться, и соотв-но в этом случае возможны такие проблемы. Если это как-то устранимо, было бы здорово.
Alias.lua (2,260 bytes)   
--http://forum.farmanager.com/viewtopic.php?f=60&t=8546
--requires FAR 3 build >=3854 (EF_OPENMODE_USEEXISTING)
local F = far.Flags
local _name = "alias.doskey"
local _filename = Macro and ... or _filename:match[[^\\%?\(.+)$]]
local _aliasfile = _filename:match[[(.+\).+$]].._name
local cmd_edit = "a"
local cmd_reload = "rr"

local flags = {EF_DISABLEHISTORY=1,EF_NONMODAL=1,EF_IMMEDIATERETURN=1,EF_OPENMODE_USEEXISTING=1}
local function EditAlias(str)
	editor.Editor (_aliasfile, _name, nil, nil, nil, nil, flags, line, nil, win.GetOEMCP()) --todo check CP
	if not Area.Editor or not str or str=="" then return end
	local n,pattern = str:len(),"^%s*"..str:lower().."%s*=" --todo find spec symbols []()%.?+-*
	for i=1,editor.GetInfo().TotalLines do
		local line = editor.GetString(nil,i,3):lower()
		if line:match(pattern) then
			editor.SetPosition (nil, i, n, nil, i-2, 1)
			editor.Select (nil, "BTYPE_STREAM", i, line:find(str), n, 1)
			--Editor.Set(2,1) --Persistent blocks
			return
			editor.Redraw()
		end
	end
	far.Message(("Could not find the string\n%q"):format(str),"Search",nil,"w")
end

if not Macro then -- Aliases: open in editor from cmdline
	EditAlias(...)
	return
end

local function Utf8ToAnsi(str)
	return win.WideCharToMultiByte(win.Utf8ToUtf16(str),win.GetACP())
end

local cmds = {
	string.format('doskey /exename=Far.exe %s=lua:@"%s" "$*"',cmd_edit,_filename),
	string.format('doskey /exename=Far.exe %s=doskey /macrofile="%s"',cmd_reload,Utf8ToAnsi(_aliasfile)),
	string.format('doskey /macrofile="%s"',Utf8ToAnsi(_aliasfile)),
}

local function Reload()
	local info = win.GetFileInfo(_aliasfile)
	if not info then
		far.Message(("File is absent: '%s'"):format(_aliasfile),"Console aliases",nil,"w")
		return
	end
	for i=1,#cmds do os.execute(cmds[i]) end
end

Event { description="Aliases: reload on edit";
	group="EditorEvent"; filemask=_name;
	condition=function(id,Event) return Event==F.EE_CLOSE end;
	action=function() 
		local EditorInfo = editor.GetInfo()
		if EditorInfo.FileName:lower()==_aliasfile:lower()
				and band(EditorInfo.CurState,F.ECSTATE_MODIFIED)~=0 then
			Reload(_aliasfile)
		end
	end;
}

Macro { description="Aliases: Load on start";
	area="Shell"; key="auto"; flags="RunAfterFARStart";
	action=Reload;
}
Alias.lua (2,260 bytes)   

DrKnS

2021-12-04 20:50

administrator   bugnote:0017272

Насколько я понимаю этот скрипт, он по таймеру (т.е. из дополнительного треда) периодически запускает внешний процесс через os.execute.
os.execute - это обертка над system(), т.е. над вызовом cmd.exe.
cmd.exe для своих целей включает esc-последовательности в консоли, запускает sqlite или что вы ему там передали, и выходит, видимо, не утруждая себя восстановлением предыдущего режима.
Far время от времени сбрасывает режим в свой и ситуация исправляется.
А под нагрузкой, видимо, лаги между этими событиями больше и вы успеваете увидеть артефакты поломанного состояния.

Far здесь точно не при чем, но в luamacro, наверное, неплохо было бы запоминать режим консоли внутри os.execute() до вызова system() и восстанавливать после.

heilong

2021-12-04 20:55

reporter   bugnote:0017273

Ваше объяснение звучит логично. А luamacro - это часть Far-а, или внешняя сторонняя библиотека? Было бы здорово эту проблему починить, на пользу всех скриптописателей, пользующихся system() / os.execute

DrKnS

2021-12-04 21:09

administrator   bugnote:0017274

Это плагин в комплекте, реализующий исполнение скриптов.

-----------

Shmuel, a это реализуемо?
Насколько я понимаю, win.system имплеменирована в luafar\ustring.c и туда это добавить можно, но os.execute берется напрямую из lua51.dll?

shmuel

2021-12-04 21:39

developer   bugnote:0017277

DrKnS, случайно заглянул сюда и увидел ваш вопрос (уведомления приходят только на открытие новых тикетов или там, где участвовал).
С данной проблемой ни разу не сталкивался.
os.execute находится в lua51.dll, не юникодная.
win.system - в Luafar3.dll, юникодная. Если нужно модифицировать, то лучше, наверное, её.

shmuel

2021-12-04 22:36

developer   bugnote:0017278

Возможно, что ничего не надо модифицировать, а просто перед os.execute вызывать panel.GetUserScreen, а после - panel.SetUserScreen.

DrKnS

2021-12-04 22:36

administrator   bugnote:0017279

Shmuel, спасибо.

Добавил в 766.

heilong, попробуйте пользоваться win.system вместо os.execute. Возможно, поможет.

shmuel

2021-12-04 22:51

developer   bugnote:0017280

DrKnS, ещё нужно обновить номер билда в version.h.

DrKnS

2021-12-04 23:42

administrator   bugnote:0017281

Спасибо, обновил.

heilong

2021-12-05 00:06

reporter   bugnote:0017282

Попробовать win.system уже сейчас, или подождать следующего nightly?

DrKnS

2021-12-05 00:16

administrator   bugnote:0017283

Попробовать с новой версией конечно же.

Уже есть там - https://github.com/FarGroup/FarManager/releases/tag/ci/v3.0.5927.2630

heilong

2021-12-09 07:38

reporter   bugnote:0017288

Попробовал с версией 5928, поменял os.execute на win.system. По-прежнему воспроизвелось.

DrKnS

2021-12-09 10:53

administrator   bugnote:0017289

Видимо, вы успеваете нажимать кнопки, пока оно еще в процессе исполнения, а с этим уже вряд ли что-то можно сделать.

heilong

2021-12-09 18:43

reporter   bugnote:0017290

Ну если ничего не поделать, то наверно чёрт с ним. В любом случае эта проблема раздражала только из-за того, что у меня этот скрипт исполнял os.execute (win.system) очень регулярно. Сейчас нужды в этом скрипте нет, а если какой-то другой скрипт использует win.system изредка, то проблемы от этого будут весьма редко.
Спасибо в любом случае )

Issue History

Date Modified Username Field Change
2021-12-04 10:23 heilong New Issue
2021-12-04 10:23 heilong File Added: 2021-12-04 11_13_37-{C__} - Far 3.0.5927.0 x64.png
2021-12-04 16:33 DrKnS Note Added: 0017262
2021-12-04 19:37 heilong Note Added: 0017267
2021-12-04 20:23 heilong Note Added: 0017269
2021-12-04 20:23 heilong File Added: Panel.ChangeDir.lua
2021-12-04 20:32 heilong Note Added: 0017270
2021-12-04 20:32 heilong File Added: Alias.lua
2021-12-04 20:50 DrKnS Note Added: 0017272
2021-12-04 20:51 DrKnS Project Far Manager => Plugins
2021-12-04 20:51 DrKnS Category Panel => General
2021-12-04 20:51 DrKnS Category General => LuaMacro / Macro Browser
2021-12-04 20:55 heilong Note Added: 0017273
2021-12-04 21:09 DrKnS Note Added: 0017274
2021-12-04 21:39 shmuel Note Added: 0017277
2021-12-04 22:36 shmuel Note Added: 0017278
2021-12-04 22:36 DrKnS Note Added: 0017279
2021-12-04 22:51 shmuel Note Added: 0017280
2021-12-04 23:42 DrKnS Assigned To => DrKnS
2021-12-04 23:42 DrKnS Status new => feedback
2021-12-04 23:42 DrKnS Note Added: 0017281
2021-12-05 00:06 heilong Note Added: 0017282
2021-12-05 00:06 heilong Status feedback => assigned
2021-12-05 00:16 DrKnS Note Added: 0017283
2021-12-09 07:38 heilong Note Added: 0017288
2021-12-09 10:53 DrKnS Note Added: 0017289
2021-12-09 18:43 heilong Note Added: 0017290
2021-12-09 18:54 DrKnS Assigned To DrKnS =>
2021-12-09 18:54 DrKnS Status assigned => closed
2021-12-09 18:54 DrKnS Resolution open => not fixable