swerg написал: Что за умопомешательство на этом https ??
Это хорошо для конечного юзера - весь трафик пересылается с шифрованием на уровне транспорта, сделанным профессионалами в этом деле, а не наколхозенным полуграмотным админом сайта. Утащить пароль или сессионный куки сниффером теперь весьма затруднительно.
Затем, это хорошо для производителей железа, криптография штука затратная, и вот уже юзер бежит за новым процессором. Особенно серверный юзер, за особенно дорогим процессором.
Затем, продажа сертификатов - отличный бизнес в стиле торговли воздухом.
Затем, это неистощимая тема для научных статей, типа гонки вооружений, одни ломают, другие укрепляют, можно вечно на этом гранты пилить.
Затем, это хлебушек для программистов, все эти изобретения надо кодить, и опасность демпинга минимальная, юные дарования ниасилят, а когда осилят, уже и сами ценник вывесят правильный.
Затем, кое-кто, может быть, имеет закладочки в сертифицированных алгоритмах, ну чисто так на всякий случай, а на фоне всеобщей уверенности, что прям вот оно тысячелетий для взлома требует, это очень удобно.
Затем, кое-какие реализации тихонько запрашивают юзерский сертификат, а кое-какие его тихонько отправляют. Можно сказать, человек с развернутым паспортом в интернет ходит. Еще удобнее.
swerg написал: но QUIK совершенно без задержек реагирует
Дайте угадаю, в мейне есть вызов какой-то сишной функции? Так-то, если в нем один луа-цикл без никто, мейн лок захватит и все, квик на первом же колбеке встанет колом, о чем тут и сообщают.
Что такое минимальные задержки, это каждый понимал по-своему ) ну, ежли задача стоит показать, как "квик тормозит в сравнении с метатрейдером", то верной дорогой пойдено.
Если в мейне ничего не делается толкового, то единственный критерий - это сколько скрипт провисит после нажатия кнопки стоп. В этом случае одна секунда нормально. Если прицеплена длл, появляются варианты: а) создать событие и ждать на нем, тогда мейн вообще не просыпается до завершения скрипта, в OnStop выставляем событие; б) в мейне цикл сообщений, тут все как обычно в винде, из OnStop посылаем сообщение потоку мейна, что пора на выход. Окон можно не создавать и использовать PostThreadMessage; в) кому охота приключениев, тот может заценить вариант с портом завершения.
одно ядро полностью будет занято, это скорей теоретическая возможность, чем то, что надо делать. Даже слип(0) уже получше будет, поток будет сниматься и вставать в конец очереди, давая прочим потокам тоже ядро поюзать. Но тоже из области поиграть с этим.
Алексей написал: попросил добавить функцию, чтобы нижние строчки со вкладками эмитентов не прыгали при нажатии с уровня на уровень
Откройте в панели управления винды апплет "источники данных (ODBC)". Там две строчки вкладок. Пощелкайте по вкладкам - они тоже прыгают, видите, да? Это так виндовый контрол "вкладки" устроен, и ваша "простенькая функция" на практике означает "арка, перепишите винду".
тоже ничего дельного не покажет, надо по всем сделкам смотреть. А вот у нас все сделки по интелу, то есть вообще все после указанного времени. Спешл фор ю спецоперацию провели. Тут как-то было обсуждение, мол да вы чо, да чтобы рынок просадить миллиард влить надо. А вот оно как на практике, ткнули одним лотом и собрали урожай. Причем явно знали, по какой цене у вас продажа, подставили покупку в точности как заказано.
Александр Волфовиц, отличный пример, как прострелить себе ногу в многопоточном окружении. Выше верно написали, мейн меняет hcc на строку как раз после проверки типа в колбеке. Обращение к глобальной переменной из разных потоков должно быть атомарным. Я б посоветовал 1) упаковать все три hcc, mcc, scc в луа-таблицу; 2) в мейне строить локально эту таблицу (а еще лучше специальную функцию написать, ее возвращающую) и сохранять в глобальную переменную одним присвоением; 3) в колбеке создавать локальную копию опять-таки одним присвоением и далее работать только с ней.
TGB написал: Обкладывать синхронизацией все используемые сишные функции в однопоточном QLua для меня неожиданное решение.
А их никто и не обкладывал. Это не аркино решение, сам луа так устроен. Все очень просто, байткод всегда выполняется под локом, а когда надо вызвать сишную функцию, лок снимается и после возврата захватывается снова. Арке надо было только реализовать lua_lock/lua_unlock, все остальное уже готово. Тут хочу добавить, что если вы в своей длл определяете сишный колбек, то он тоже без лока выполняется (в отличие от луа-колбека). И это отличное место, где можно прострелить себе ногу.
Цитата
TGB написал: Вообще, в однопоточном QLua можно было бы практически полностью отказаться от всякой синхронизации и от модификации исходного Lua.
Исходный луа практически не модифицирован, добавлены только колбеки, предусмотренные в луа для взаимодействия с хостом. Сама qlua.dll ничего не хачит, использует луа как положено через стандартный апи, что местами не очень эффективно, но идеологически правильно.
Насчет однопоточности - так можно было сделать с самого начала, теперь что-то переделывать, похоже, поздновато. И у такого решения есть минус, на момент выборки сообщения в потоке скрипта общее состояние квика уже другое. Сравните с виндовыми очередями сообщений, где позиция мыши и нажатые клавиши сохраняются для каждого сообщения, какими они были на момент генерации сообщения, это вот пример, какие сложности возникают. И арке пришлось бы тоже подобным заниматься, закончилось бы полным дампом состояния, прицепленным к каждому сообщению. А как есть - вам дали колбек, квик вас ждет в колбеке, вы забираете то, что нужно именно вам и отправляете в мейн. Тоже не все гладко, кое-что все равно асинхронно даже в колбеке, но это мизер по сравнению с адом, который был бы с наглухо зашитыми в qlua очередями.
local run = true
local nshow = 0
function OnAllTrade()
if nshow < 10 then
PrintDbgStr('OnAllTrade')
nshow = nshow + 1
end
end
function dummy(i)
local a = math.sqrt(math.sqrt(1.0 * i) * math.sqrt(2.0 * i))
end
function main()
PrintDbgStr('Before loop')
for i = 0, 10000000 do
dummy(i)
end
PrintDbgStr('After loop')
end
TGB написал: Между сообщениями 'Before loop' и 'After loop' ни одно сообщение 'OnAllTrade' не вклинилось.
Значит увеличьте длину цикла или усложните вычисления в dummy, цикл просто быстро закончился. Вы обнаружили, что на время вызова любой сишной функции (а не только sleep) луа снимает лок, и сделали неправильный вывод, подумав только на sleep. В качестве такой функции может выступить и message, как в примере, и любая встроенная в луа библиотечная функция, и любая функция qlua. И так всегда было, это не новость в последней версии.
TGB, неправда. Если бы было правдой, в следующем скрипте между сообщениями 'Before loop' и 'After loop' ни одно сообщение 'OnAllTrade' вклиниться не могло бы (слипа в мейне нет, следовательно, колбеки не должны выполняться, согласно вашей модели). А они вклиниваются.
Код
local run = true
local nshow = 0
function OnAllTrade()
if nshow < 100 then
message('OnAllTrade')
nshow = nshow + 1
end
end
function dummy(i)
local a = math.sqrt(1.0)
end
function main()
message('Before loop')
for i = 0, 10000000 do
dummy(i)
end
message('After loop')
end
Хотел было, но Диего любит наворотить в проекте нетривиальностей, что в двух словах не объяснишь, так что проще самому собрать (не тестировано вообще никак, может и нерабочее получилось).
Так-то компилятор (одного файла) выглядит вот так и запускается в самом квике (куда уж совместимее-то)
Код
-- compilation arguments
local srcname = getScriptPath() .. '\\test.lua'
local dstname = getScriptPath() .. '\\test.out'
local strip_debug_info = false
-- the compiler itself
function main()
local chunk, err = loadfile(srcname, 't')
if nil == chunk then
error('Compilation error:\n' .. err)
end
local bin = string.dump(chunk, strip_debug_info)
local f = io.open(dstname, 'wb')
if nil == f then
error('Unable to create the destination file')
end
f:write(bin)
f:flush()
f:close()
end
С учетом sleep(1) есть неиллюзорные шансы, что мейн завершается раньше sendTransaction из колбека. Что будет, если в OnTransReply строку run = nil перенести после sendTransaction?
Алексей написал: непонятно, то что этот буфер функция сама не освобождает после отработки и приходится ждать сборщика мусора.
Утечкой это нельзя назвать, утечка это когда утекло с концами. В конкретном случае буфер выделяется под строку с отформатированной датой. Луа отформатировал дату, пытается пихнуть строку на стек, а такая строка уже есть от прошлого вызова, отсюда периодичность прирастания минутная или секундная в зависимости от формата. Затем дата поменялась, луа таки засунул новую строку в стек, а старая улетела в мусор и дело за коллектором, когда он там соблаговолит. Еще и поинтересней есть закидоны, коллектор определяет лимит, исходя из занятой памяти, и иногда при медленном нарастании может решить, что вообще все ок и прибираться рановато, и при следующем подходе опять, и так будет постепенно память прирастать, вроде и мусор, а вроде и прибираться перманентно рановато. Дергайте collectgarbage, если напрягает.
Ага. Смотрите, вы купили позавчера канистру бензина и вылили в бочку, вчера купили еще одну и вылили в ту же бочку, сегодня вы хотите из бочки залить в бак. Ваш вопрос: как залить именно тот бензин, что был куплен позавчера? Ответ: а никак, он весь одинаковый. Заливайте сколько надо и считайте, что залили именно позавчерашний.
TGB написал: можно бы было как то использовать и его исходники
Они уже присутствуют в 8.11 в несколько модифицированном виде, только не работают, то ли не включили асинхронные исключения при компиляции, то ли замодифицировали до смерти.
Roman Azarov написал: предоставьте, пожалуйста, скрипт, на котором она воспроизводится
Сейчас я могу предоставить кое-что получше. Вот здесь архив с тем же скриптом и - новое - (весьма приблизительной) копией вашей lua53.dll, собранной из обычного луа 5.3.5 и палок. Распаковать все в папку рабочего места с заменой оригинальной lua53.dll, запустить скрипт. Через секунду скрипт выбросит ACCESS VIOLATION - смотрите, как исключение будет обработано, - точно так же, как любая другая ошибка луа, без повреждения состояния квика, без деактивации кнопки "запустить" и прочих прелестей. Сравните с поведением оригинальной lua53.dll. Вот что ожидалось увидеть после добавления приведенного выше кода, но что-то пошло не так.
Уже выкладывал скрипт + длл для выбрасывания исключений в колбеках, может облегчат работу. Удобнее всего в OnStop бросать, при запущенном скрипте ставим брейкпойнты перед и после LUAI_TRY, жмем остановить, убеждаемся, что на брейкпойнте ДО остановились, жмем продолжить и по идее должны остановиться на брейкпойнте ПОСЛЕ, а по факту улетаем в qlua.dll. У меня, к сожалению, сорцев и символов нет, наглядно на скринах показать не получится.
Roman Azarov написал: в чем именно заключается проблема?
У меня - ни в чем, я как бы предложил некое улучшение, его как бы реализовали, мои тесты показали, что оно никогда не сработает в текущем виде почему-то. Как брейкпойнт поставить я думаю в арке все знают, куда поставить написано выше. Тут вопрос надо ли оно кому-то. Ежли нет, так мне меньше всех.
swerg написал: Волшебно работать с какой-то одной версией - это поможет.А вот с двумя разными одновременно в рамках одной dll...
Тоже можно, хотя на самом деле я считаю, что создание одной универсальной длл - это создание себе геморроя. В том числе жаль, что арка пошла по этому пути, а не сделала отдельный плагин под каждую версию луа. Как говорится, сложность программы растет, пока не превысит способностей программиста, так зачем приближать этот момент.
Александр написал: lua_getextraspace - опять же надо загружать какую-то из этих DLL
Не то чтобы загружать, а получить хэндл. Если длл отсутствует, то и печалиться не о чем, она никак нас не могла запустить. Вот вариант извлечения прицепленной к стейту версии. Возвращает версию числом или 0, если ничего не удалось выудить. На 5.3 и 5.4 попробовал, 5.1 нет под рукой, чисто "а чо ей не работать-то".
swerg написал: мы должны иметь две полных структуры адресов Lua-API функций для разных версий Lua и вставлять проверку в каждую функцию библиотеку, доступную для Lua-скрипта, переключаясь на адреса нужной версии Lua для каждой интерфейсной функции нашей библиотеки....
Вот так в квике и сделано. Есть lua_getglobal51, lua_getglobal53, теперь и lua_getglobal54, и есть lua_getglobalX, которая из переданного стейта выуживает версию и дергает нужный вариант функции. И так все. Сам квик всегда использует lua_*X, для него разницы нет, в какой версии скрипт выполняется, если еще десяток версий добавят, основной код и не заметит. Честно говоря, думал, что это временное-переходное решение, но вот с добавлением 5.4 стало ясно, что так и останется.
Александр написал: Я изучил структуры lua_State для луа 5.3 и 5.4 и они различны. Если поле status <> 0, то это lua5.3, иначе lua5.4.
Тоже в эту сторону смотрел, показалось ненадежным. Там есть еще одно интересное место, если уже привязываться к версии и немного хачить: к стейту прицеплена юзердата, сам квик по ней версию и определяет (несколько запутанным способом, я не понял, как именно). Получить можно с помощью экспортируемой luaI_getextraspace или (раз уж хачить) просто как ((char *)pstate) - 8, оно во всех версиях луа одинаково. А уж дальше порыться там.
Уже обновил и даже попробовал. Код с транслятором в lua53.dll увидел (и в lua54.dll тоже), а вот работающим его не увидел. Предполагаю потому, что lua53.dll собрали без флага /EHa, других объяснений не могу придумать. Транслятор перед вызовом колбека ставится, но при исключении в колбеке оно улетает по-прежнему в qlua.dll и ловится уже там, то есть по-прежнему весь хвост в luaD_rawrunprotected и выше не выполняется. Чтобы это увидеть, достаточно поставить брейкпойнт в luaD_rawrunprotected сразу после блока LUAI_TRY и бросить из колбека access violation или что-то подобное. Если исключение поймано, квик встанет на брейкпойнте, но этого не происходит, ближайшее место, где удалось его остановить, это транслятор в qlua.dll, то есть где и раньше.
Как запретить QUIK добавлять инструменты самостоятельно?, Кто-то подкидывает в Текущие торги торговые инструменты по своему усмотрению, как бездомных котят..
Выше глупость написал, конечно, мы и так знаем, из какой длл lua_version дернули. Но вот хотел проверить на практике и узрел очень интересную штуковину. Тксть внимание на экран. Запускаем скрипт, грузящий нашу длл, через "запустить в луа 5.3.5", смотрим, какой стейт нам дали Теперь запускаем через "запустить в луа 5.4.1", смотрим, какой стейт нам дали Это изыск дизайна или это лютый косяк?
Александр написал: Не подходит, т. к. в Lua 5.4 lua_version просто возвращает номер версии, а при передаче в luastate от Lua 5.4 в функцию lua_version от Lua 5.3 происходит ACCESS_VIOLATION.Еще варианты?
Еще вариант - не передавать в lua_version указатель на стейт, а передавать NULL, это защитит от акцесс виолейшена (как?). В этом случае 5.3 вернет указатель на статический номер версии, а 5.4 вернет число с номером версии. Далее исходим из факта, что указатель никак не может быть меньше 64 килобайт, винда из этого тоже всегда исходит, так что безопасно. Значит, ежли получили меньшее число - это напрямую номер версии, а если большее - это указатель на номер версии, разыменовываем и получаем сам номер. Костыльное решение, конечно, но рабочее.
swerg написал: 2) В списке исправленных недоработок есть несколько пунктов про Lua (пункты 10, 11, 12, 13)Подразумевается, что указанные в них проблемы исправятся только при использовании Lua 5.4 ? или для Lua 5.3 они исправлены тоже?
Значицо, что мы видим по некоторым из этих пунктов.
1. С lua_checkstack (п.11) вроде все порешали, натыкали везде и вроде везде с правильным размером. Считаем вопрос закрытым. Работать будет во всех версиях, это уже над луа находится.
2. С SEH-исключениями (п.12) пока могу сказать только про 5.3. Видно, что старались, но, кажется, забыли флаг /EHa компилятору поставить, поэтому транслятор в lua53.dll теперь есть, но не срабатывает при исключении, исключение таки долетает до qlua.dll и ловится уже там старым транслятором и старой ловушкой, которые, к счастью, пока не убрали. Так что тут еще надо допиливать.
В целом, беглым взглядом глядя, по луа работа большая проделана.
P.S. Для сотрудников арки и внешних желающих поковырять исключения предлагаю простой комплект - длл, генерирующая разные виды исключений (+сорцы), и скриптик к ней. Раскомментируем в скрипте по строчечке и смотрим, как квик соответствующее исключение вылавливает. В арке могут также поставить бряк на новый транслятор и убедиться, что никогда он не выполняется.
Виталий написал: Как сам факт поддержки CLR (без каких-либо вызовов) влияет на выгрузку библиотеки?
Влияет так, что загрузчик, видя clr в загружаемом модуле, загружает дотнет, и дальнейшим циклом жизни модуля управляет уже дотнет. Квик ни сном ни духом не ведает, что в него вперли аппдомен и его надо прибивать, соответственно никто его и не прибивает, соответственно длл выгружена не будет.
Виталий написал: если есть ошибка в dll, насколько припоминаю, квик вывалит ошибку и захлопнется. Разве нет?
Не обязательно, lua_error из длл можно смело генерировать, они ловятся как обычные ошибки скрипта. Плюсовые исключения тоже ловятся, даже некоторые seh, но эти повреждают квику кишки и потом могут быть последствия. А вот если стек попортить, квик ничего не заметит и может на этом потом или упасть, или накосячить.
Виталий написал: Во-вторых, Старатель в комменте выше предоставил исчерпывающий пример, если моих кодов мало.
Он подтвердил то, что в моем вопросе подразумевалось: при ошибке в длл она не выгружается. Это не очень здорово, но это и не нормальная рабочая ситуация. По существу варианта два: а) в 8.10 что-то накосячили с выгрузкой (проверить не могу); б) в вашей длл есть ошибка (проверить не могу). Из уже показанного я бы предложил перед lua_pushstring добавить lua_checkstack. Хотя вряд ли это причина, это намекает на то, что длл сделана без должного пристрастия к деталям, в коих диавол.