Ruby% x разветвляется на 64-битной Linux, но не на 32, и только с определенным синтаксисом - PullRequest
2 голосов
/ 18 октября 2008

Вот код Ruby:

puts %x{ pstree #{$$} }   # never forks
puts %x{ pstree '#{$$}' } # forks on amd64 only

На 32-битной Ubuntu Dapper я получаю такой вывод:

t.rb---pstree
t.rb---pstree

Что имеет смысл для меня. Но на 64-битной Ubuntu Hardy я получаю следующее:

t.rb---sh---pstree
t.rb---pstree

Здесь показано, что Ruby разветвляется перед выполнением только в одном из случаев. Когда я помещаю код в файл и запускаю его под strace -fF, кажется, что на 64-битном Hardy он вызывает clone() (как fork()) до execve(), тогда как на 32-битном Dapper это не так вещь.

Мои версии Ruby:

ruby 1.8.4 (2005-12-24) [i486-linux]
ruby 1.8.6 (2007-09-24 patchlevel 111) [x86_64-linux]

Я должен попытаться смешивать и сопоставлять переводчики, ОС и размеры слов, но сейчас это нелегко, поскольку я не администрирую эти машины. Может быть, кто-то из вас скажет мне, в чем разница даже между этими командами в 64-битной системе, не говоря уже о том, почему они работают одинаково в 32-битной системе.

Ответы [ 2 ]

2 голосов
/ 18 октября 2008

Ruby выполняет расширение оболочки, когда% x используется с одним аргументом (как вы делаете).

Вот мое предположение относительно того, что происходит:

Ruby сканирует команду, чтобы определить, существуют ли какие-либо специальные символы, которые могут привести к необходимости выполнения расширения оболочки, и в этом случае она вызывает оболочку для этого. Во втором примере одинарных кавычек достаточно, чтобы Ruby захотел вызвать оболочку для расширения, отсюда и ответвление. В первом примере Ruby может определить, что расширение оболочки не требуется, так как команда не содержит специальных символов (после раскрытия переменной), следовательно, нет разветвления. Разница между этими двумя версиями, вероятно, связана с внутренним изменением того, как ruby ​​пытается определить, необходимо ли расширение оболочки. Я получаю форк для второго примера на ruby ​​1.8.5 на 32-битной машине.

[EDIT]

Хорошо, я взглянул на исходный код для ruby ​​1.8.4 и 1.8.6, и обе версии используют одни и те же критерии, чтобы определить, следует ли вызывать оболочку для выполнения расширения оболочки, если существует какой-либо из следующих символов в командной строке оболочка будет вызвана, если указан один аргумент для% x:

*?{}[]<>()~&|\\$;'`"\n

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

/bin/sh -c "pstree $$"

Это команда, которую Ruby использует для выполнения pstree в примере с кавычками на обеих машинах. Вы должны увидеть bash---pstree на 32-битной машине и bash---sh---pstree на другой.

Так что теперь мне интересно, что привело вас к обнаружению этой разницы и вызывает ли она проблему?

1 голос
/ 24 сентября 2011

Я прошел через эту ситуацию, разработав асинхронную работу процессора с серией подпроцессов (форка), и это произошло, когда мастер находился на переднем плане и получил SIGINT.

Я запускаю: ставит «результат% (задание с задержкой монстра)»

и вывод был только: "результат"

  • Да, я "ловушка" SIGINT в мастере

Andre

...