<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title><![CDATA[QUIK -> DDE &mdash; Исследование последних 5 сек. жизни LUA-скрипта в QUIK]]></title>
		<link>https://quik2dde.ru/viewtopic.php?id=23</link>
		<atom:link href="https://quik2dde.ru/extern.php?action=feed&amp;tid=23&amp;type=rss" rel="self" type="application/rss+xml" />
		<description><![CDATA[Недавние сообщения в теме «Исследование последних 5 сек. жизни LUA-скрипта в QUIK».]]></description>
		<lastBuildDate>Tue, 17 Sep 2013 19:59:25 +0000</lastBuildDate>
		<generator>PunBB</generator>
		<item>
			<title><![CDATA[Re: Исследование последних 5 сек. жизни LUA-скрипта в QUIK]]></title>
			<link>https://quik2dde.ru/viewtopic.php?pid=428#p428</link>
			<description><![CDATA[<p><span style="color: #DDDDDD">&lt; reserved &gt;</span></p>]]></description>
			<author><![CDATA[null@example.com (admin)]]></author>
			<pubDate>Tue, 17 Sep 2013 19:59:25 +0000</pubDate>
			<guid>https://quik2dde.ru/viewtopic.php?pid=428#p428</guid>
		</item>
		<item>
			<title><![CDATA[Re: Исследование последних 5 сек. жизни LUA-скрипта в QUIK]]></title>
			<link>https://quik2dde.ru/viewtopic.php?pid=47#p47</link>
			<description><![CDATA[<p><span style="color: #007744">Это пост оставил просто для истории, как было в самой первой версии, когда появилась возможность писать скрипты на Lua в QUIK.</span></p><p><strong>Замечание</strong>: <em>исследования проводились на терминале QUIK версии <strong>6.4.0.169</strong>, возможно в других версиях будут какие-то отличия</em>.</p><p>Открыл таблицу &quot;Всех сделок&quot;, запустил скрипт. Через некоторое время нажал на кнопку &quot;Остановить&quot;.<br />Через 8 сек. терминал QUIK упал с какой-то внутренней ошибкой, а я пошел смотреть лог.</p><p>Начало лога выглядит так:<br /></p><div class="codebox"><pre><code>01/06/13 00:04:55 OnInit
01/06/13 00:04:55 OnAllTrade
01/06/13 00:04:55 OnAllTrade
01/06/13 00:04:55 OnAllTrade
01/06/13 00:04:55 main start
01/06/13 00:04:55 main process
01/06/13 00:04:55 OnAllTrade
01/06/13 00:04:55 OnAllTrade</code></pre></div><p>Что здесь интересно: несмотря на то, что запись &quot;main start&quot; в лог-файл стоит первой строкой в <strong>main</strong>, однако до собственно старта этой функции вполне могут быть вызваны другие обработчики (что мы видим на примере 3-х строк OnAllTrade), если соответствующие события происходят достаточно часто. Т.е. все инициирующие действия в скрипте обязательно необходимо выполнить в обработчике <strong>OnInit</strong>.</p><p>В середине лог-файла идут вперемешку записи &quot;main process&quot; и &quot;OnAllTrade&quot;, это понятно, эту часть я опускаю. Интересное происходит в конце:<br /></p><div class="codebox"><pre><code>01/06/13 00:05:05 OnAllTrade
01/06/13 00:05:05 main process
01/06/13 00:05:05 main process
01/06/13 00:05:06 main process
01/06/13 00:05:06 OnStop start
01/06/13 00:05:06 OnStop process
01/06/13 00:05:06 main process
01/06/13 00:05:06 OnStop process
01/06/13 00:05:07 main process
01/06/13 00:05:07 OnStop process
01/06/13 00:05:07 main process
01/06/13 00:05:07 OnStop process
01/06/13 00:05:08 main process
01/06/13 00:05:08 OnStop process
01/06/13 00:05:08 main process
01/06/13 00:05:08 OnStop process
01/06/13 00:05:09 main process
01/06/13 00:05:09 OnStop end
01/06/13 00:05:09 main process
01/06/13 00:05:10 main process
01/06/13 00:05:10 main process
01/06/13 00:05:11 main process
01/06/13 00:05:11 main process
01/06/13 00:05:12 main process
01/06/13 00:05:12 main process
01/06/13 00:05:13 main process
01/06/13 00:05:13 main process
01/06/13 00:05:14 main process </code></pre></div><p>Здесь приведены буквально все последние строки из лога. Что тут видно:<br /></p><ul><li><p>В 00:05:06 нажата кнопка &quot;Завершить&quot; (запись в логе &quot;OnStop start&quot;), после чего видим поочередно идущие записи &quot;OnStop process&quot; и &quot;main process&quot; раз в пол-секунды.</p></li><li><p>Через 3 секунды в 00:05:09 завершается работа OnStop (запись в логе &quot;OnStop end&quot;), после чего в течение 5 секунд, т.е. до 00:05:14 в логе есть записи и работе функции main &quot;main process&quot;. Таким образом с момента нажатия &quot;Завершить&quot; прошло 8 сек, и только после этого скрипт был остановлен.</p></li><li><p>Отмечу также, что после начала работы OnStop в логе нет ни одной записи про вызов OnAllTrade, хотя до этого такие события происходили крайне часто.</p></li></ul><br /><p><strong>Из всего этого можно сделать такие выводы</strong>:<br /></p><ol class="decimal"><li><p>5 секунд на завершение функции main дается после завершения обработчика <strong>OnStop</strong>, а не после нажатия на кнопку &quot;Завершить&quot; (что соответствует документации).</p></li><li><p>После вызова <strong>OnStop</strong> и до самого окончаня работы скрипта никакой другой обработчик (кроме работы функции <strong>main</strong>) не вызывается; во время работы OnStop отсутствие вызовов понятно: эта функция работает в том же потоке, что и другие обработчики, а потому пока она не завершится, другие вызваны быть не могут; а дальше, думаю, ожидание завершения main (т.е. отдельного потока) организовано в основном же потоке терминала, причем &quot;жестким тупым циклом&quot;, а не на объектах синхронизации с тайм-аутом, использование которых наверное дало бы возможность отработать еще и другим обработчикам; нельзя сказать, что это недочет, просто такая реализация.</p></li><li><p>То, что терминал &quot;упал&quot; после принудительного завершения <strong>main</strong> связано, думаю, с тем, что, как известно, в исследуемой версии 6.4.0.169 присутствует ошибка вызова обработчиков [url=http://forum-archive.quik.ru/forum/lua/96866/96911/#m96911]после завершения скрипта[/url]; я думаю, что вызов <strong>OnTrade</strong> после завершения скрипта (и, наверное, завершении работы виртуальной LUA-машины) приводит к каким-то разрушительным последствиям, из-за чего терминал падает; справедливость такой версии можно будет проверить позже, когда указанная ошибка будет исправлена.</p></li></ol>]]></description>
			<author><![CDATA[null@example.com (admin)]]></author>
			<pubDate>Sat, 05 Jan 2013 19:19:13 +0000</pubDate>
			<guid>https://quik2dde.ru/viewtopic.php?pid=47#p47</guid>
		</item>
		<item>
			<title><![CDATA[Исследование последних 5 сек. жизни LUA-скрипта в QUIK]]></title>
			<link>https://quik2dde.ru/viewtopic.php?pid=46#p46</link>
			<description><![CDATA[<p><span style="color: #3F9439"><strong>Обновлено: 24.12.2012</strong></span><br />(по сравнению с предыдущим вариантом данного материала помимо проверки на новой версии QUIK еще проведено исследование событий, происходящих при закрытии терминала)</p><p><strong>Замечание</strong>: <em>исследования проводились на терминале QUIK версии <strong>6.8.4.14</strong>, возможно в других версиях будут какие-то отличия</em>.</p><br /><p>В описании обработчика <strong>OnStop</strong> в документации QLUA есть примечание:<br /><em>&quot;После окончания выполнения функции таймаут завершения работы скрипта 5 секунд. По истечении этого интервала функция main() завершается принудительно.&quot; </em></p><p>Стало интересно точно разобраться со следующими моментами:<br /></p><ul><li><p>сколько времени после нажатия кнопки &quot;Завершить&quot; еще может жить скрипт на самом деле?</p></li><li><p>от какого момента времени отсчитываются указанные 5 секунд?</p></li><li><p>вызываются ли в течение этих 5 секунд какие-либо другие обработчики?</p></li><li><p>вызываются ли после остановки скрипта какие-либо обработчики кроме OnStop()?</p></li><li><p>что происходит с работающими скриптами в момент закрытия терминала?</p></li></ul><p>Для этого сделал такой простенький скрипт:</p><div class="codebox"><pre><code>f = nil

function writeToLog(proc_name)
    f:write(os.date() .. &quot; &quot;.. proc_name .. &quot;\n&quot;)
    f:flush()
end

function OnInit(path)
    f = io.open(path .. &quot;.out&quot;, &quot;w+t&quot;)
    writeToLog(&quot;OnInit&quot;)
end

function OnStop(signal)
    writeToLog(&quot;OnStop start&quot;)
    local i
    for i = 1, 6 do
        writeToLog(&quot;OnStop process&quot;)
        sleep(500)
    end
    writeToLog(&quot;OnStop end&quot;)
end

function OnClose()
    writeToLog(&quot;OnClose start&quot;)
    local i
    for i = 1, 6 do
        writeToLog(&quot;OnClose process&quot;)
        sleep(500)
    end
    writeToLog(&quot;OnClose end&quot;)
end

function main()
    writeToLog(&quot;main start&quot;)
    while true do
        writeToLog(&quot;main process&quot;)
        sleep(500)
    end
    writeToLog(&quot;main stop&quot;)
end

function OnAllTrade(trade)
    writeToLog(&quot;OnAllTrade&quot;)
end</code></pre></div><p>Что здесь есть:<br /></p><ul><li><p><strong>writeToLog</strong> - записывает переданную строку в в лог-файл</p></li><li><p>обработчик <strong>OnInit</strong> - создает лог-файл с именем <em><strong>&lt;имя-файла-lua&gt;.out</strong></em>, после чего в него записываются вызовы всех имеющихся функций</p></li><li><p>обработчик <strong>OnStop</strong> - содержит цикл задержки на 3 секунды (путем вызова 6 раз sleep на пол-секунды), чтобы можно было понять от какого момента отсчитываются 5 секунд; во время задержки раз в пол секунды производится запись в лог о работе OnStop</p></li><li><p>обработчик <strong>OnClose</strong> - содержит цикл задержки на 3 секунды (путем вызова 6 раз sleep на пол-секунды), чтобы можно было понять что еще обрабатывается в терминале; во время задержки раз в пол секунды производится запись в лог о работе OnClose</p></li><li><p>обработчик <strong>main</strong> - здесь просто вставлен бесконечный цикл, который никогда не завершается, при этом для того, чтобы можно было видеть работу main, раз в пол-секунды пишется запись в лог-файл</p></li><li><p>обработчик <strong>OnAllTrade</strong> - добавлен для того, чтобы можно было понять вызываются ли обработчики во время 5-ти секундного ожидания завершения работы скрипта или нет; выбран именно этот обработчик из тех соображений, что данное событие происходит очень часто; разумеется, в терминале открыта таблица всех сделок</p></li></ul><br /><p>Запустил скрипт. Через некоторое время нажал на кнопку &quot;Остановить&quot;.<br />Через 8 сек. скрипт остановился (видно по диалогу скриптов Lua), запись в лог прекратилась. Что же там в логе?</p><p>Начало лога выглядит так:<br /></p><div class="codebox"><pre><code>09/18/13 02:40:25 OnInit
09/18/13 02:40:25 OnAllTrade
09/18/13 02:40:25 OnAllTrade
09/18/13 02:40:25 OnAllTrade
09/18/13 02:40:25 main start
09/18/13 02:40:25 main process
09/18/13 02:40:25 OnAllTrade
09/18/13 02:40:25 OnAllTrade
09/18/13 02:40:25 OnAllTrade</code></pre></div><p>Что здесь интересно: несмотря на то, что вывод в лог текста &quot;main start&quot; стоит первой строкой внутри функции <strong>main()</strong>, однако до собственно старта этой функции (т.е. соотв. записи в лог) вполне могут быть вызваны другие обработчики (что мы видим на примере 3-х строк OnAllTrade), если соответствующие события происходят достаточно часто. Отсюда вывод: все инициирующие действия в скрипте обязательно необходимо выполнить внутри обработчика <strong>OnInit</strong>, т.к. только он гарантированно будет выполнен до запуска отдельного потока с main().</p><p>В середине лог-файла идут вперемешку записи &quot;main process&quot; и &quot;OnAllTrade&quot;, это понятно, эту часть я опускаю. Интересное происходит в конце:<br /></p><div class="codebox"><pre><code>09/18/13 02:40:31 main process
09/18/13 02:40:31 OnAllTrade
09/18/13 02:40:31 OnAllTrade
09/18/13 02:40:31 OnAllTrade
09/18/13 02:40:31 OnAllTrade
09/18/13 02:40:32 main process
09/18/13 02:40:32 OnStop start
09/18/13 02:40:32 OnStop process
09/18/13 02:40:32 main process
09/18/13 02:40:33 OnStop process
09/18/13 02:40:33 main process
09/18/13 02:40:33 OnStop process
09/18/13 02:40:33 main process
09/18/13 02:40:34 OnStop process
09/18/13 02:40:34 main process
09/18/13 02:40:34 OnStop process
09/18/13 02:40:34 main process
09/18/13 02:40:35 OnStop process
09/18/13 02:40:35 main process
09/18/13 02:40:35 OnStop end
09/18/13 02:40:35 main process
09/18/13 02:40:36 main process
09/18/13 02:40:36 main process
09/18/13 02:40:37 main process
09/18/13 02:40:37 main process
09/18/13 02:40:38 main process
09/18/13 02:40:38 main process
09/18/13 02:40:39 main process
09/18/13 02:40:39 main process
09/18/13 02:40:40 main process</code></pre></div><p>Здесь приведены буквально все последние строки из лога. Что тут видно:<br /></p><ul><li><p>В 02:40:32 нажата кнопка &quot;Завершить&quot; (запись в логе &quot;OnStop start&quot;), после чего видим поочередно идущие записи &quot;OnStop process&quot; и &quot;main process&quot; раз в пол-секунды.</p></li><li><p>Через 3 секунды в 02:40:35 завершается работа OnStop (запись в логе &quot;OnStop end&quot;), после чего в течение 5 секунд, т.е. до 02:40:40 в логе есть записи о работе функции main() - &quot;main process&quot;. Таким образом с момента нажатия &quot;Завершить&quot; прошло 8 сек, и только после этого скрипт был остановлен.</p></li><li><p>Отмечу также, что после начала работы OnStop больше в логе нет ни одной записи про вызов OnAllTrade, хотя до этого такие события происходили крайне часто.</p></li></ul><br /><p><strong>Из всего этого можно сделать следующие выводы</strong>:<br /></p><ol class="decimal"><li><p>5 секунд на завершение функции main() дается с момента после завершения обработчика <strong>OnStop()</strong>, а не с момента нажатия на кнопку &quot;Завершить&quot; (что соответствует документации). Т.е. сам обработчик OnStop() может работать сколько угодно времени.</p></li><li><p>После вызова <strong>OnStop()</strong> и до самого окончания работы скрипта никакой другой обработчик (кроме работы функции <strong>main</strong>) не вызывается; во время работы OnStop() отсутствие вызовов понятно: эта функция работает в том же потоке, что и другие функции обратного вызова, а потому пока OnStop() не завершится, другие вызваны быть не могут; а дальше, думаю, ожидание завершения main (т.е. отдельного потока) организовано в основном потоке терминала, причем &quot;жестким тупым циклом&quot;, а не на объектах синхронизации с тайм-аутом, использование которых наверное дало бы возможность отработать еще и другим обработчикам; нельзя сказать, что это недочет, просто такая реализация. Хотя, конечно, хорошо бы документировать тот факт, что другие обработчики после OnStop() уже не работают.</p></li></ol><br /><p>После этого я снова запустил скрипт и закрыл терминал QUIK.</p><p>Что произошло: окно терминала тут же исчезло, однако запись в лог продолжалась! Т.е. скрипт продолжал работать. Впрочем, примерно тоже самое время, вот финальный фрагмент лога для этого случая:</p><div class="codebox"><pre><code>09/18/13 02:44:02 OnAllTrade
09/18/13 02:44:02 OnAllTrade
09/18/13 02:44:02 OnAllTrade
09/18/13 02:44:02 main process
09/18/13 02:44:03 OnClose start
09/18/13 02:44:03 OnClose process
09/18/13 02:44:03 main process
09/18/13 02:44:03 OnClose process
09/18/13 02:44:03 main process
09/18/13 02:44:04 OnClose process
09/18/13 02:44:04 main process
09/18/13 02:44:04 OnClose process
09/18/13 02:44:04 main process
09/18/13 02:44:05 OnClose process
09/18/13 02:44:05 main process
09/18/13 02:44:05 OnClose process
09/18/13 02:44:05 main process
09/18/13 02:44:06 OnClose end
09/18/13 02:44:06 OnStop start
09/18/13 02:44:06 OnStop process
09/18/13 02:44:06 main process
09/18/13 02:44:06 OnStop process
09/18/13 02:44:06 main process
09/18/13 02:44:07 OnStop process
09/18/13 02:44:07 main process
09/18/13 02:44:07 OnStop process
09/18/13 02:44:07 main process
09/18/13 02:44:08 OnStop process
09/18/13 02:44:08 main process
09/18/13 02:44:08 OnStop process
09/18/13 02:44:08 main process
09/18/13 02:44:09 OnStop end
09/18/13 02:44:09 main process
09/18/13 02:44:09 main process
09/18/13 02:44:10 main process
09/18/13 02:44:10 main process
09/18/13 02:44:11 main process
09/18/13 02:44:11 main process
09/18/13 02:44:12 main process
09/18/13 02:44:12 main process
09/18/13 02:44:13 main process
09/18/13 02:44:13 main process</code></pre></div><ul><li><p>Вначале 3 секунды работает OnClose()</p></li><li><p>Затем 3 секунды работает OnStop()</p></li><li><p>После чего еще 4 секунды (вероятно, это погрешность изменений) работает main(), после чего скрипт останавливается и процесс терминала QUIK info.exe прекращает работу (исчезает из диспетчера задач)</p></li><li><p>Отмечу также, что после закрытия терминала вызываются только OnClose() и OnStop(). Ни одной записи про вызов OnAllTrade() больше нет.</p></li></ul><br /><p><strong>Из этого можно сделать дополнительные выводы</strong>:<br /></p><ol class="decimal"><li><p>И при закрытии терминала, и при остановке его кнопкой &quot;Остановить&quot; диалога Lua-скриптов всегда будет самым последним вызван OnStop(), причем в случае закрытия терминала он будет вызван после OnClose().</p></li></ol><br /><p>По результатам была [url=https://quik2dde.ru/viewtopic.php?id=16]обновлена картинка[/url] в части места отсчета 5-ти секундного интервала.</p><p>Архив со скриптом и полным логом [url=https://quik2dde.ru/static-img/test-5-sec.zip]здесь[/url].</p>]]></description>
			<author><![CDATA[null@example.com (admin)]]></author>
			<pubDate>Sat, 05 Jan 2013 19:18:02 +0000</pubDate>
			<guid>https://quik2dde.ru/viewtopic.php?pid=46#p46</guid>
		</item>
	</channel>
</rss>
