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

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

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

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

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

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

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

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

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

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

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

17 ответов

2 просмотра

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

maplum- Автор вопроса
Den 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 походит на некорректную отладку многопотока, такого не бывает, выведи в отладчике себе окно со списком потоков и гляди на каком именно потоке остановился отладчик

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

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

Сообщение* в закодированном виде. То есть, просто сделать sendMessage?text=Привет бла-бла! не получится, надо в HEX переводить, и добавлять процент, типа такого: sendMessage?t...
КТ315
21
А случайно нет ли в паскале штатной возможности передать указатель и количество туда где array of в качестве аргумента?
zamtmn
25
Anyone here suffers from unexplained aural migraines, who would be up for talking for a bit? Doesn't *have* to be aural, but I am not asking about headaches, I mean actual mi...
Martin Rys
58
Всем привет. Испытываю проблемы в работе БД, а именно огромного роста логов, такого характера: 024-05-16 18:39:07 +05 sentry sentry [unknown] 1050169 7-1 app-sentry01.corp.ru>...
Alexey
2
Если подытожить: По мнению Розыча и Хемуля и др. - предпочтительно по возможности объявлять в секции имплементации потому-что: 1) Выше скорость компиляции 2) Не замусоривается...
notme
7
Ну раз я пока тут, задам пару глупых вопросов. Зачем писать на ассемблере если компилятор довольно умный, а ассемблер много времени занимает? В каких прикладных задачах сейчас...
Максим Рябцев
20
Хм. А телеграм апи работают через HTTP?
The Bird of Hermes
14
Почему Telegram пишет, что объект media не найден, хотя на самом деле я его передаю? Делаю на urllib, без зависимостей, так надо. Вызываю метод sendMediaGroup с таким JSON: ...
Alexey S
1
В дельфе нет никакого коробочного (без установки третьих либ) способа получить CallStack с расшифровкой отладочных символов?
notme
7
Приветики всем!)) Подскажите: есть функция, которая записывает число типа Cardinal в четыре байта, хранимые в TBytes. Можете помочь мне, показав, как должна выглядеть функци...
Моринаро
5
Карта сайта