169 похожих чатов

Мне консультация нужна, есть процедура, нереентерабельная, и в неё из

двух-трех потоков приходит вызов. Как мне блокировать остальные вызовы, пока я один отрабатываю?

Что-то вроде CriticalSection, пока он не завершился, все остальные вызовы холдятся.

Да есть, всякие Mutex, Critical Section и прочий вагон добра, м.б уже решал кто эту проблему?

Вот как выглядит в асме:

Non_reentrant_fn: push rcx rdx rbx
Lock (resource)
Blablabla...

Так вот пока я делаю push регистров, прилетает второй и третий вызов моей функции. Т.к стек общий, он тотально портится и программа крашится.

Без сохранения регистров вначале - никак, т.к Lock(resource) портит регистры.

Примерно такая же проблема, как с DOS, в котором нельзя было вызывать самого себя из-за нереентерабельности.

Как бы решить эту проблему?

17 ответов

12 просмотров

так откуда вызовы то прилетают с других потоков в один стэк? Или с одного потока?

maplum- Автор вопроса
Денис Фомин Fomin
так откуда вызовы то прилетают с других потоков в ...

Собственный перехватчик mfc-шной dll, в части CInternetSession:GetHTTPConnection, вызывается из одной dll-ки, которая дергается из нескольких потоков. Т.е выглядит так Thread1: call MainDll, call CInternetSession:GetHTTPConnection Thread2: call MainDll, call CInternetSession:GetHTTPConnection На GetHTTPConnection висит собственный хук, который решает пускать далее в mfc-шный GetHTTPConnection или внутри себя обрабатывать

Меняй архитектуру, если, конечно, ты контролируешь код той функции...

maplum- Автор вопроса
maplum
Что бог послал, на том и работаю)))

Я прочитал, но та и не понял почему процедура не реентерабельна? И как так получается, что при каждом вызове общий стек?

maplum- Автор вопроса
maplum
Я смотрю по значению rsp

Что у тебя за отладчик?

maplum
IDA

У тебя точка останова на входе в твою процедуру?

maplum- Автор вопроса
disba1ancer
У тебя точка останова на входе в твою процедуру?

Да, и перед вызовом собственной процедуры и в ней

maplum
Да, и перед вызовом собственной процедуры и в ней

Ты уверен, что у тебя эта точка останова отлавливается в одном потоке?

maplum- Автор вопроса
disba1ancer
Ты уверен, что у тебя эта точка останова отлавлива...

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

maplum
Да, а ей больше некуда деваться. При входе в мою п...

Вот еще почитай, может это поможет навести порядок: В Windows x86-64 используется единое соглашение вызовов __fastcall. Первые четыре целочисленных аргумента (слева направо) передаются в 64-битных регистрах RCX, RDX, R8 и R9. Остальные аргументы (целочисленные) передаются через стек (справа налево). Указатель this всегда хранится в регистре RCX. Даже если аргумент передан в регистре, вызывающая функция обязана резервировать для него место в стеке, уменьшая значение регистра RSP. За очистку стека отвечает вызывающая функция

maplum- Автор вопроса
maplum
У меня все процедуры по конвенции fastcall

Вот можно как сделать, что то типа такого generate $id; mutex $id; while i=1 $id.lock(); i=1; ..yourprogram.. i=0; $id.unlock(); только i надо обьявить в статике где то повыше чтоли или какой то другой триггер общий использовать семафор, можно тогда вообще без мутексов обойтись только while и скобками наверное это псевдокод ;) Вот такую функцию можно в качестве глобального счетчика использовать, прошу прощения за небольшой офтоп ну это в тему: HANDLE CreateSemaphore ( LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, // атр. доступа LONG lInitialCount, // начальное состояние счетчика LONG lMaximumCount, // макс кол-о обращений LPCTSTR lpName // имя объекта ); Это видимо надо в отдельном процессе создавать который не будет дуплицироваться BOOL ReleaseSemaphore ( HANDLE hSemaphore,// указатель на семафор LONG lReleaseCount, // на сколько изменять счетчик LPLONG lpPreviousCount // предыдущее значение ); В случае успеха возвращаемое значение — не ноль. —

maplum
У меня все процедуры по конвенции fastcall

Взаимодействие с винапи должно идти по его соглашению по, а не так как ты себе напридумывал

maplum
Да, а ей больше некуда деваться. При входе в мою п...

Произвольное изменение rip походит на некорректную отладку многопотока, такого не бывает, выведи в отладчике себе окно со списком потоков и гляди на каком именно потоке остановился отладчик

Похожие вопросы

Обсуждают сегодня

30500 за редактор? )
Владимир
47
а через ESC-код ?
Alexey Kulakov
29
Чёт не понял, я ж правильной функцией воспользовался чтобы вывести отладочную информацию? но что-то она не ловится
notme
18
Добрый день! Скажите пожалуйста, а какие программы вы бы рекомендовали написать для того, чтобы научиться управлять памятью? Можно написать динамический массив, можно связный ...
Филипп
7
У меня есть функция где происходит это: write_bit(buffer, 1); write_bit(buffer, 0); write_bit(buffer, 1); write_bit(buffer, 1); write_bit(buffer, 1); w...
~
14
Недавно Google Project Zero нашёл багу в SQLite с помощью LLM, о чём достаточно было шумно в определённых интернетах, которые сопровождались рассказами, что скоро всех "ибешни...
Alex Sherbakov
5
Ребят в СИ можно реализовать ООП?
Николай
33
Как передать управляющий символ в открытую через CreateProcess консоль? Собсна, есть процедура: procedure TRedirectThread.WriteData(Data: OEMString); var Written: Cardinal;...
Serjone
6
https://github.com/erlang/otp/blob/OTP-27.1/lib/kernel/src/logger_h_common.erl#L174 https://github.com/erlang/otp/blob/OTP-27.1/lib/kernel/src/logger_olp.erl#L76 15 лет назад...
Maksim Lapshin
20
Всем привет! Имеется функция: function IsValidChar(ch: UTF8Char): Boolean; var i: Integer; ValidChars: AnsiString; begin ValidChars := 'abcdefghijklmnopqrstuvwxyzABCDE...
Евгений
44
Карта сайта