W>То есть при входе в сопрограмму нужно модифицировать _NT_TIB::StackBase/StackLimit на новый стек, и как-то правильно построить _NT_TIB::ExceptionList? А как мне достучаться к "текущей" _NT_TIB? Я, вообще, не бред говорю?
Не, не бред. Кстати, может вам нужны fiber'ы?
На x86 TEB лежит начиная с FS:[0], удобный адрес TEB в селекторе DS мона достать в FS::[18]
Как много веселых ребят, и все делают велосипед...
[]
O>>1) цепочка SEH обработчиков, начинающаяся с _NT_TIB::ExceptionList невалидна O>>2) текущий esp не укладывается в _NT_TIB::StackBase/StackLimit
W>То есть при входе в сопрограмму нужно модифицировать _NT_TIB::StackBase/StackLimit на новый стек, и как-то правильно построить _NT_TIB::ExceptionList? А как мне достучаться к "текущей" _NT_TIB? Я, вообще, не бред говорю? :)
Сделай свой обработчик VEH и диспатчи исключения в нем, поскольку VEH отрабатывает до SEH.
Что-то типа
"компактные" — это что? в каком смысле?
W>4. Сопрограммы вообще могут быть портабельными в пределах Win32-Unix(MacOS)?
да. см выше.
W>5. А как с мобильными платформами? Android дружит с этим? Он же вроде потомок Unix. А iOS?
см выше.
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Здравствуйте, Went, Вы писали:
W>1. Можно ли как-то "пропатчить" SetThreadContext и GetThreadContext чтобы исключения работали?
Не использовать SetThreadContext, а использовать CreateFiber.
W>2. POSIX-функции getcontext/setcontext/makecontext/swapcontext на Unix-ах дружат с исключениями?
Да
W>3. boost.Coroutines — стоящая вещь? Она делает хорошие портабельные и компактные сопрограммы? Или она тоже работает только в тепличных условиях?
Без поддержки со стороны компилятора сопрограммы в C++ реализовать полностью нельзя. Ну или настолько сложно, что этого никто ещё не сделал.
Типичная проблема как раз связана с обработкой исключений. Например, если оно было выброшено из одной из сопрограмм, то нужно передать его в другие параллельно работающие сопрограммы, завершить часть из них, учесть возможность, что исключение может поймать другая сопрограмма или, если этого не произошло, пробросить исключение в главный поток — это очень сложно без правки компилятора.
Частичная поддержка (без обработки сложных исключений) вполне возможна.
W>4. Сопрограммы вообще могут быть портабельными в пределах Win32-Unix(MacOS)?
С учетом предыдущих оговорок, вполне. У нас используется setcontext для Unix, fibers для Windows и setjmp для других странных платформ.
W>5. А как с мобильными платформами? Android дружит с этим? Он же вроде потомок Unix.
Android же вообще не unix.
Здравствуйте, Went, Вы писали:
W>Здравствуйте, watch-maker, Вы писали:
WM>>Как минимум отсутствует выравнивание стека. На x86-64 скорее всего упадёт, на x86 выравнивания оказывается достаточно, но, это как бы тоже без гарантий работы.
W>По какому базису его нужно выравнивать?
Зависит от процессора и используемых соглашений о вызове (что в свою очередь зависит от ОС и компилятора). Фактически сейчас достаточно выравнивать на границу 16 байт — это минимум для типичных вызовов в x86-64 и минимум для некоторых вызовов в x86.
Здравствуйте, Went, Вы писали:
W>Здравствуйте. Думаю, вопрос уже немало обсосан, но осмелюсь поднять очередную тему. W>Реализовал сопрограммы используя WinAPI-функции SetThreadContext и GetThreadContext.
Неправильное решение. Используй CreateFiber и SwitchToFiber
W>1. Можно ли как-то "пропатчить" SetThreadContext и GetThreadContext чтобы исключения работали?
Для решения "CreateFiber" это не нужно — для SEH (и исключений MSVC) все будет работать "из коробки".
Единственное, что категорически не рекомендуется — это выпускать исключение из сопрограммы. То есть, функция сопрограммы толжна быть завернута в "try{}catch(...){/*ничего*/}"
W>2. POSIX-функции getcontext/setcontext/makecontext/swapcontext на Unix-ах дружат с исключениями? Или вообще такой подход нежизнеспособен?
Дружат, точнее DWARF-исключениям на них пофигу. А для SjLj-исключений (но это устаревшая архаика) придется малеха похачить.
W>3. boost.Coroutines — стоящая вещь? Она делает хорошие портабельные и компактные сопрограммы? Или она тоже работает только в тепличных условиях?
Не знаю.
W>4. Сопрограммы вообще могут быть портабельными в пределах Win32-Unix(MacOS)?
Да. Я реализовал достаточно мелкий класс для работы с сопрограммами. Работает на юнихах через setcontext, на выни — через CreateFiber. Исключения везде работают (даже SjLj, но это больше из любви к искусству).
W>5. А как с мобильными платформами? Android дружит с этим? Он же вроде потомок Unix. А iOS?
На андроиде — Жаба. Если хочется нативщины (и геморроя), то линух. То есть, setcontext должон работать.
__________
16.There is no cause so right that one cannot find a fool following it.
Здравствуйте. Думаю, вопрос уже немало обсосан, но осмелюсь поднять очередную тему.
Реализовал сопрограммы используя WinAPI-функции SetThreadContext и GetThreadContext. Точнее, я подглядел как это сделал другой человек Он эмулировал ими стандартные POSIX-функции getcontext/setcontext/makecontext/swapcontext и потом, на их основе "возвел" класс сопрограммы. Все работает четко, но исключения не ловятся То есть если я внутри сопрограмммы напишу:
try
{
throw 1;
}
catch(int)
{
},
то исключение не словится, будет unhadled exception. Это делает меня плакать, я о сопрограммах джва года мечтал Соответственно, вопросы знатокам:
1. Можно ли как-то "пропатчить" SetThreadContext и GetThreadContext чтобы исключения работали?
2. POSIX-функции getcontext/setcontext/makecontext/swapcontext на Unix-ах дружат с исключениями? Или вообще такой подход нежизнеспособен?
3. boost.Coroutines — стоящая вещь? Она делает хорошие портабельные и компактные сопрограммы? Или она тоже работает только в тепличных условиях?
4. Сопрограммы вообще могут быть портабельными в пределах Win32-Unix(MacOS)?
5. А как с мобильными платформами? Android дружит с этим? Он же вроде потомок Unix. А iOS?
W>Здравствуйте. Думаю, вопрос уже немало обсосан, но осмелюсь поднять очередную тему. W>Реализовал сопрограммы используя WinAPI-функции SetThreadContext и GetThreadContext. Точнее, я подглядел как это сделал другой человек Он эмулировал ими стандартные POSIX-функции getcontext/setcontext/makecontext/swapcontext и потом, на их основе "возвел" класс сопрограммы. Все работает четко, но исключения не ловятся То есть если я внутри сопрограмммы напишу:
винда не ловит исключения если
1) цепочка SEH обработчиков, начинающаяся с _NT_TIB::ExceptionList невалидна
2) текущий esp не укладывается в _NT_TIB::StackBase/StackLimit
Как много веселых ребят, и все делают велосипед...
Здравствуйте, ononim, Вы писали:
W>>Здравствуйте. Думаю, вопрос уже немало обсосан, но осмелюсь поднять очередную тему. W>>Реализовал сопрограммы используя WinAPI-функции SetThreadContext и GetThreadContext. Точнее, я подглядел как это сделал другой человек Он эмулировал ими стандартные POSIX-функции getcontext/setcontext/makecontext/swapcontext и потом, на их основе "возвел" класс сопрограммы. Все работает четко, но исключения не ловятся То есть если я внутри сопрограмммы напишу: O>винда не ловит исключения если O>1) цепочка SEH обработчиков, начинающаяся с _NT_TIB::ExceptionList невалидна O>2) текущий esp не укладывается в _NT_TIB::StackBase/StackLimit
То есть при входе в сопрограмму нужно модифицировать _NT_TIB::StackBase/StackLimit на новый стек, и как-то правильно построить _NT_TIB::ExceptionList? А как мне достучаться к "текущей" _NT_TIB? Я, вообще, не бред говорю?
Здравствуйте, niXman, Вы писали:
X>Здравствуйте, Went, Вы писали: W>>2. POSIX-функции getcontext/setcontext/makecontext/swapcontext на Unix-ах дружат с исключениями? Или вообще такой подход нежизнеспособен? X>да. дружат. однажды использовал для подобной задачи. с исключениями проблем не было.
Это радует. Ибо на Win32 без допилки (спасибо ononim) не работало
W>>3. boost.Coroutines — стоящая вещь? Она делает хорошие портабельные и компактные сопрограммы? Или она тоже работает только в тепличных условиях? X>да — портабельные. ибо не использует ничего платформозависимого. посмотри такую реализацию(читать именно с этом порядке): X>http://blog.think-async.com/2009/07/wife-says-i-cant-believe-it-works.html X>http://blog.think-async.com/2009/08/secret-sauce-revealed.html X>http://blog.think-async.com/2009/08/composed-operations-coroutines-and-code.html X>http://blog.think-async.com/2010/03/potted-guide-to-stackless-coroutines.html
Это очень мило Но хотелось бы настоящих сорутин, чтобы со стеком
А разве boost.Coroutines не используют ничего платформеннозависимого? Как они тогда стек двигают?
X>"компактные" — это что? в каком смысле?
Ну, чтобы не приходилось писать специальный синтаксис для функций. Как в приведенном выше примере.
W>>4. Сопрограммы вообще могут быть портабельными в пределах Win32-Unix(MacOS)? X>да. см выше.
W>>5. А как с мобильными платформами? Android дружит с этим? Он же вроде потомок Unix. А iOS? X>см выше.
Здравствуйте, Patalog, Вы писали:
P>Сделай свой обработчик VEH и диспатчи исключения в нем, поскольку VEH отрабатывает до SEH.
То есть это способ руками обрабатывать исключения? Без try/catch ?
Здравствуйте, ononim, Вы писали:
W>>То есть при входе в сопрограмму нужно модифицировать _NT_TIB::StackBase/StackLimit на новый стек, и как-то правильно построить _NT_TIB::ExceptionList? А как мне достучаться к "текущей" _NT_TIB? Я, вообще, не бред говорю? O>Не, не бред. Кстати, может вам нужны fiber'ы? O>На x86 TEB лежит начиная с FS:[0], удобный адрес TEB в селекторе DS мона достать в FS::[18]
Вот это да! Какие, оказывается, дебри можно потянуть из невинной функции __readfsdword! Действительно, если указать правильные _NT_TIB::StackBase/StackLimit до вызова функции SetThreadContext, а также обнулить для нового контекста _NT_TIB::ExceptionList, то все начинает ловиться! Огромное спасибо
Здравствуйте, Went, Вы писали:
W>А разве boost.Coroutines не используют ничего платформеннозависимого? Как они тогда стек двигают?
Только платформозависимое и используют. Для каждой платформы (ОС + компилятор) пишется свой код с ассемблерными вставками и прочими ужасами. Потом при копиляции через define выбирается нужный участок, остальное игнорируется.
Здравствуйте, Went, Вы писали:
W>Здравствуйте, Patalog, Вы писали:
P>>Сделай свой обработчик VEH и диспатчи исключения в нем, поскольку VEH отрабатывает до SEH. W>То есть это способ руками обрабатывать исключения? Без try/catch ?
Нет, это способ их диспатчить, поскольку штатный диспетчер не взлетает, скорее всего по тем причинам, которые озвучил ononim.
Кстати, /nosafeseh пробовал?
Здравствуйте, watch-maker, Вы писали:
WM>Только платформозависимое и используют. Для каждой платформы (ОС + компилятор) пишется свой код с ассемблерными вставками и прочими ужасами. Потом при копиляции через define выбирается нужный участок, остальное игнорируется.
Вот и я про это. Просто мне из прошлого сообщения показалось, что niXman считает, что там нет ничего специфического.
Здравствуйте, watch-maker, Вы писали:
WM>Не использовать SetThreadContext, а использовать CreateFiber.
Ну, вроде помогла "магия" прямой записи в TIB
WM>Да
WM>Частичная поддержка (без обработки сложных исключений) вполне возможна.
Ну, это то что мне нужно.
WM>С учетом предыдущих оговорок, вполне. У нас используется setcontext для Unix, fibers для Windows и setjmp для других странных платформ.
WM>Android же вообще не unix.
Точно, он Linux. Но Linux тоже POSIX, поэтому на нем должны быть setcontext?
Здравствуйте, Went, Вы писали:
W> какие могут быть проблемы? Пока что тестил на Win32
Как минимум отсутствует выравнивание стека. На x86-64 скорее всего упадёт, на x86 выравнивания оказывается достаточно, но, это как бы тоже без гарантий работы.
Здравствуйте, Went, Вы писали:
WM>>Не использовать SetThreadContext, а использовать CreateFiber. W>Ну, вроде помогла "магия" прямой записи в TIB
Жуть, конечно. К чёрту такую магию, fibers куда как лучше
WM>>Android же вообще не unix. W>Точно, он Linux. Но Linux тоже POSIX, поэтому на нем должны быть setcontext?
Не, тут всё не так.
В Android используется ядро Linux, но и только. Оно недоступно извне, да даже до glibc доступа нет.
С таким же успехом можно поставить Windows на VirtualBox на Ubuntu и говорить, что Windows превратилась в unix-систему, — конечно же это не так, ведь из такой установки Windows получить доступ к ядру Linux нельзя, — там непреодалимый барьер, всё закрыто.
Здравствуйте, watch-maker, Вы писали:
WM>Как минимум отсутствует выравнивание стека. На x86-64 скорее всего упадёт, на x86 выравнивания оказывается достаточно, но, это как бы тоже без гарантий работы.
Здравствуйте, watch-maker, Вы писали:
W>>По какому базису его нужно выравнивать? WM>Зависит от процессора и используемых соглашений о вызове (что в свою очередь зависит от ОС и компилятора). Фактически сейчас достаточно выравнивать на границу 16 байт — это минимум для типичных вызовов в x86-64 и минимум для некоторых вызовов в x86.
Здравствуйте, Went, Вы писали:
W>Здравствуйте, watch-maker, Вы писали:
WM>>Только платформозависимое и используют. Для каждой платформы (ОС + компилятор) пишется свой код с ассемблерными вставками и прочими ужасами. Потом при копиляции через define выбирается нужный участок, остальное игнорируется. W>Вот и я про это. Просто мне из прошлого сообщения показалось, что niXman считает, что там нет ничего специфического.
ошибся. сорри
Currently the library uses fibers on Win32 systems, custom assembler code on the very specific "GCC-linux-x86 using frame-unwind-tables based exception handling and a generic makecontext/setcontext based implementation on POSIX 2001 compliant systems. Note that, as the POSIX standard knows nothing about C++, this is not guaranteed to work on all platforms. Also the interaction between threads and user contexts is not specified by the standard.
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Здравствуйте, Went, Вы писали:
W>Кстати, а главному потоку нужно делать ConvertThreadToFiber?
ConvertThreadToFiber нужно вызывать тем нитям (threads), которые будут вызывать другие fibers. Остальныем нитям можно эту функцию не вызывать.
Здравствуйте, Went, Вы писали:
W>Здравствуйте, 0xDEADBEEF, Вы писали:
DEA>>Неправильное решение. Используй CreateFiber и SwitchToFiber
W>Кстати, а главному потоку нужно делать ConvertThreadToFiber? Это не создаст каких-то проблем в будущем?
Надо. Иначе, ты не сможешь сказать "SwitchToFiber" на основную нитку — т.к. GetCurrentFiber() для нее будет возвращать говно.
То есть, не получится реализовать "yield" — переключение на основную нитку до завершения сопрограммы.
Но, ConvertThreadToFiber — функция гадкая. Она (а)каждый раз выделяет где-то память (б)нет документированных способов узнать, что на нитке эта функция была вызвана или нет.
Для решения этой проблемы я использую такой вот хак:
if( 0x00001E00 == (DWORD)::GetCurrentFiber() )
::ConvertThreadToFiber(NULL);//Fiber stuff wasn't initialized for current thread
//this is genuine hack, but it appears it works for all MS OSes
__________
16.There is no cause so right that one cannot find a fool following it.
Здравствуйте, 0xDEADBEEF, Вы писали:
DEA>Но, ConvertThreadToFiber — функция гадкая. Она (а)каждый раз выделяет где-то память (б)нет документированных способов узнать, что на нитке эта функция была вызвана или нет. DEA>Для решения этой проблемы я использую такой вот хак: