Setjmp/longjmp в продолжении Ruby

Я задавался этим вопросом, копаясь в коде cont.c в текущей версии Ruby. В документации setjmp говорится, что вызов longjmp для структуры jmp_buf после возврата вызывающего объекта setjmp является ошибкой. Но, кажется, Ruby делает это счастливо и не падает:

https://github.com/ruby/ruby/blob/05f087c844f0e1e7cfe323edcf591de64069a289/cont.c#L522 https://github.com/ruby/ruby/blob/05f087c844f0e1e7cfe323edcf591de64069a289/cont.c#L775 (+ еще пара вариантов использования с волокнами)

И я спрашиваю: как это возможно?

Я заметил, что тот же исходный код также использует set/getcontext, но только с волокнами или вроде того. Мне кажется более разумным использовать именно эти функции, а не set/longjmp.


person themarketka    schedule 17.02.2015    source источник
comment
Неопределенное поведение, но обычно оно работает так, как ожидалось.   -  person cremno    schedule 17.02.2015
comment
Извините, но эти примеры вызывают ruby_setjmp(), а не setjmp(). Является ли первое оберткой второго? Если да, возможно ли, что у него есть инструментарий для выполнения этой работы (например, создание дубликата фрейма стека или выполнение какой-либо другой магии, позволяющей соответствующему (ruby_)longjmp() работать)?   -  person John Bollinger    schedule 18.02.2015
comment
@cremno хорошо, я ожидал чего-то подобного. Но не очень утешительно, если честно.   -  person themarketka    schedule 18.02.2015
comment
@JohnBollinger По сути, это псевдоним: #define ruby_setjmp(env) RUBY_SETJMP(env) #define RUBY_SETJMP(env) _setjmp(env) И почти то же самое для ruby_longjmp.   -  person themarketka    schedule 18.02.2015
comment
Это не так просто, поскольку CRuby может использовать __builtin_setjmp(), _setjmp(), sigsetjmp(), setjmp() или setjmpex() вместо RUBY_SETJMP(). Вероятно, все эти варианты также не определяют это. На самом деле, если вы посмотрите над вызовом `ruby_longjmp()`, вы увидите некоторый код, связанный с контекстом стека.   -  person cremno    schedule 18.02.2015