Waiter!

Здесь можно найти готовые «кирпичики» — части кода, пригодные для построения более крупных проектов, а также решения различных типовых и не очень задач на VB.

Модератор: Brickgroup

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Waiter!

Сообщение GSerg » 21.02.2005 (Пн) 15:15

Данный кирпич позволяет ожидать завершения некоторых операций (как то: работы других процессов, установления ивентов, мьютексов, семафоров и всяких других синхронизационных штук) без блокирования основного потока программы.

По сравнению с первой версией из Проектов произошла большая чистка, изменение логики, фиксинг багов и апгрейд функциональности. Данный кирпич считать версией 1.0 :)

Апдейт 1.1
Добавлена возможность узнавать хэндлы, которые ожидает Waiter! в настоящий момент.

Апдейт 1.2 (27 ноября 2006)
Совместимость с DEP (см. комментарии в исходном коде контрола)
Вложения
Waiter.zip
Waiter!
Ожидание любого HANDLE без блокирования основного потока программы.
(6.65 Кб) Скачиваний: 513
Последний раз редактировалось GSerg 27.11.2006 (Пн) 12:18, всего редактировалось 5 раз(а).
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

dimix
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 174
Зарегистрирован: 08.02.2005 (Вт) 22:47

Сообщение dimix » 25.02.2005 (Пт) 13:16

GSerg, в этом кирпиче ожидается закрытие блокнота. Но блокнот должен закрыть юзер. А если Shell'ом вызываем приложение (выполняется в DOS-окне), которое отрабатывает и закрывается само, есть ли возможность (конечно, интересует применительно к Waiter) понять, закрылось приложение само (отработав) или его закрыл пользователь? Не тянет на версию 1.1? Или все гораздо сложнее? :roll:

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 25.02.2005 (Пт) 13:44

Всё гораздо сложнее :)
Только само приложение получает запрос на выход, в котором указывается причина. С точки зрения других процессов есть только "работает/не работает". Это вопрос межпроцессного сабклассинга, а не функций синхронизации :)
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 25.11.2006 (Сб) 14:41

Напоминание автору: данный кирпич несовместим с DEP.
Изображение

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 25.11.2006 (Сб) 14:43

Угу.
Потому что информацию о GlobalAlloc подправили в MSDN с того момента, как я ею пользовался.
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 27.11.2006 (Пн) 5:19

Выложена новая версия, совместимая с DEP.

Текст коммента из контрола:
При написании Waiter'а я прекрасно помнил о DEP, которая, если включена в Windows, не даст выполнить код, сгенерированный в памяти, если на этой памяти нет флага, разрешающего выполнение кода. В моём MSDN говорилось, что функция GlobalAlloc отводит память уже с этим флагом, и особо подчёркивалось, что для выполнения сгенерированного в ней кода больше ничего не нужно.

Однако, тестирование Waiter'а на компьютере с аппаратной поддержкой DEP показало, что он вылетает с исключением защиты памяти. В онлайновом же MSDN к тому моменту всё уже было подправлено: для функции GlobalAlloc уже говорилось, что никаких исполняемых флагов она не ставит, и что для выполнения сгенерированного кода надо самому ставить нужный флаг защиты через VirtualProtect.

Посему, Waiter был немного переписан в части отведения памяти, однако, остался один нюанс.

Если использовать VirtualAlloc для изначального выделения памяти, то с безопасностью всё в порядке, однако отводится целая страница памяти (у меня, например, это 4 Кб), что гораздо больше, чем нужно. Хотя, один экземпляр Waiter'а коммиттит целый мегабайт памяти в качестве стека для нового потока (если, конечно, вы не подправили PE-заголовок файла), так что на этом фоне 4 дополнительных Кб выглядят ничтожно.

Если же использовать GlobalAlloc с последующим VirtualProtect, то память будет расходоваться более эффективно, т.к. GlobalAlloc сохраняет определённую информацию между вызовами себя, и потому выделяет следующий кусок из той же страницы, что и предыдущий, но в этом случае может возникнуть та ситуация, что я своим VirtualProtect сниму нужный флаг защиты со страницы памяти, которая была отведена при помощи GlobalAlloc родительским приложением, в котором находится Waiter. Хотя, вред от этого увидеть весьма трудно, поскольку устанавливаемый мною режим доступа самый широкий, без ограничений, а режимы copy-on-write для памяти, отведённой через GlobalAlloc, недоступны.

Поэтому! Способ отведения памяти регулируется через условную компиляцию.
По умолчанию выбран безусловно безопасный вариант, с VirtualAlloc.
Кому надо, включайте обратно GlobalAlloc. Константа вот:

#Const USE_VIRTUAL_ALLOC = True
Последний раз редактировалось GSerg 27.11.2006 (Пн) 12:15, всего редактировалось 2 раз(а).
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 27.11.2006 (Пн) 8:36

GSerg писал(а):Если использовать VirtualProtect для изначального выделения памяти

Опечатка?

GSerg писал(а):однако отводится целая страница памяти (у меня, например, это 4 Кб)

У всех остальных так же.
Изображение

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 27.11.2006 (Пн) 12:12

tyomitch писал(а):Опечатка?

Опечатка.

tyomitch писал(а):У всех остальных так же.

Тогда почему для узнавания этой цифры советуют юзать GetSystemInfo? :)
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16473
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 03.08.2007 (Пт) 16:41

Описание GlobalAlloc писал(а):
...
All memory is created with execute access; no special function is required to execute dynamically generated code.

...


Раз уж я наступил на эти же грабли, задам вопрос тут:

sombody писал(а):Учитывая, что где-то написано, что в какой-то из осей права на выполнение только из VirtualAlloc.
Короче, там где работает DEP не получится выставить право на исполнение через VirtualProtect. Тока из VirtualAlloc


Правда?
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 03.08.2007 (Пт) 17:01

Хакер писал(а):
Описание GlobalAlloc писал(а):All memory is created with execute access; no special function is required to execute dynamically generated code.

Тухлое твоё описание.

Подлинное описание GlobalAlloc писал(а):To execute dynamically generated code, use the VirtualAlloc function to allocate memory and the VirtualProtect function to grant PAGE_EXECUTE access.



Хакер писал(а):Правда?

Windows 2003 EE SP2, Pentium D.
Код: Выделить всё
typedef void myproc();

int main(int argc, char* argv[])
{
   myproc* p = (myproc*)GlobalAlloc(GPTR,100);
   *((char*)p)=0xC3;
   p();
   return 0;
}


The instruction at "0x00155700" referenced memory at "0x00155700". The memory could not be "written".
Последний раз редактировалось tyomitch 03.08.2007 (Пт) 17:03, всего редактировалось 1 раз.
Изображение

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16473
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 03.08.2007 (Пт) 17:03

tyomitch
Причём тут GlobalAlloc ?
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 03.08.2007 (Пт) 17:05

Хакер писал(а):Причём тут GlobalAlloc ?

Так ведь ты первый начал цитировать её тухлое описание.
Изображение

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16473
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 03.08.2007 (Пт) 17:23

Первым о тухлости описания начал говорить GSerg:
В моём MSDN говорилось, что функция GlobalAlloc отводит память уже с этим флагом, и особо подчёркивалось, что для выполнения сгенерированного в ней кода больше ничего не нужно.


Итак, мне потребовалось генерить динамический код. GlobalAlloc - подумал я (я ведь не знал что в старом описании такая ошибка :x ). Меня ждал облом. Пошёл смотреть сюда - ага, есть такое дело.

Мне нужно размещать в памяти маленькие процедурки (отличающиеся друг-от-друга одним лишь DWORD-ом).

Выход: можно резервировать и коммитить для них страницы памяти, самому следить когда коммитить новую страницу под функции, самому дефрагментировать страницы (да - ведь процедурки будут и удаляться, причём в абсолютно хаотичном порядке).

Никаких проблем нет, разве что реализовывать менеждер памяти для всего этого дела - влом и некогда.

Второй вариант: переложить всё это на плечи ОС. И размещать процедурки скажем в куче (а почему бы и нет?). Но у кучи изначально нет execute-права. Значит надо сделать страницы кучи исполнимыми с помощью VirtualProtect (а почем бы и нет?). Но если в какой-то системе попытка "grant PAGE_EXECUTE access" с помощью VirtualProtect обломится (об этом ведь говорил somebody), то я вынужден юзать первый вариант (т.е. управлять памятью самостоятельно).

Вот я и спрашиваю, правда ли то, что
somebody писал(а):в какой-то из осей права на выполнение только из VirtualAlloc.
Короче, там где работает DEP не получится выставить право на исполнение через VirtualProtect. Тока из VirtualAlloc
.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 03.08.2007 (Пт) 17:38

Платформа та же.

Код: Выделить всё
typedef void myproc();

int main(int argc, char* argv[])
{
   myproc* p = (myproc*)GlobalAlloc(GPTR,100);
   printf("%d\n", VirtualProtect(p, 100, PAGE_EXECUTE_READWRITE, NULL));
   printf("%d\n", GetLastError());
   return 0;
}


0
998


Как будто бы тебе призыва юзать VirtualAlloc из подлинного MSDN мало?
Изображение

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16473
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 03.08.2007 (Пт) 17:41

Нельзя NULL передавать 4-ым аргументов VirtualProtect :?

Там должен быть валидный для записи адрес.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

ANDLL
Великий гастроном
Великий гастроном
Аватара пользователя
 
Сообщения: 3450
Зарегистрирован: 29.06.2003 (Вс) 18:55

Сообщение ANDLL » 03.08.2007 (Пт) 18:27

Хакер писал(а):Выход: можно резервировать и коммитить для них страницы памяти, самому следить когда коммитить новую страницу под функции, самому дефрагментировать страницы (да - ведь процедурки будут и удаляться, причём в абсолютно хаотичном порядке).

Никаких проблем нет, разве что реализовывать менеждер памяти для всего этого дела - влом и некогда.

Второй вариант: переложить всё это на плечи ОС. И размещать процедурки скажем в куче (а почему бы и нет?). Но у кучи изначально нет execute-права. Значит надо сделать страницы кучи исполнимыми с помощью VirtualProtect (а почем бы и нет?). Но если в какой-то системе попытка "grant PAGE_EXECUTE access" с помощью VirtualProtect обломится (об этом ведь говорил somebody), то я вынужден юзать первый вариант (т.е. управлять памятью самостоятельно).
Эмм, а чем не устраивает куча windows с HEAP_CREATE_ENABLE_EXECUTE?
Гастрономия - наука о пище, о ее приготовлении, употреблении, переварении и испражнении.
Блог

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16473
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 03.08.2007 (Пт) 19:39

ANDLL
В моём локальном MSDN такой константы нет :)

И да, - чем она GSerg-а не устраивает? (это ему вопрос)
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 03.08.2007 (Пт) 22:18

Хакер писал(а):И да, - чем она GSerg-а не устраивает?

GSerg'а устраивает текущее состояние Waiter'а. При этом GSerg не исключает, что существуют иные способы достижения его работоспособности. Их непредставленность в текущей реализации объясняется как тем, что я запросто могу не знать о них, так и тем, что Waiter является кирпичом-чёрным ящиком, а не демонстрацией как можно большего количества способов заставить его работать.

Что касается высказывания somebody о невозможности использования VirtualProtect, то в MDSN как раз и указывается, что при включенном DEP как раз надо менять защищённость памяти через VirtualProtect (в частности, рекомендуется сначала ставить право на запись, генерировать и писать туда код, снимать право на запись и ставить право на чтение и выполнение).
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас


Вернуться в Кирпичный завод

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 6

    TopList