Menu
Categories
empty-expect и сборка под архитектуру PowerPC
April 22, 2014 Сеть и интернет

Некоторые консольные приложения несмотря на интуитивную предрасположенность к скриптовой автоматизации предполагают интерактивное взаимодействие с пользователем, что напрочь убивает любые попытки составления простых скриптов для автоматического выполнения тех или иных действий с их помощью.

Для исправления ситуации существуют немногочисленные программы, позволяющие создавать своего рода псевдотерминалы, отслеживающие появление на консоли того или иного текста и позволяющие задать текст, автоматически отправляемый в ответ на данный текст. Типовым примером является утилита expect, требующая для работы интерпретатора tcl, или значительно более легкая и значительно менее известная утилита empty, заметно более подходящая для OpenWrt-роутеров.

В случае попытки запуска утилиты empty на роутере, работающем на процессоре архитектуры PowerPC (в частности, mpc85xx), обнаруживается, что любые действия приводят к ее моментальному сбою с сообщением о segfault’е (SIGSEGV) в системном логе:

Tue Apr 22 00:07:26 2014 kern.info kernel: [885768.318640] empty[9029]: unhandled signal 11 at 00004000 nip 4806f2a4 lr 10002180 code 30001

В ходе изучения исходников empty.c была выявлена особенность gcc-компилятора, что при вызове функции semctl() без четвертого параметра, который, в общем-то, должен бы являться необязательным, под архитектуру PowerPC генерируется некорректный код. Описание и workaround для данной проблемы представлен, к примеру, здесь (к слову, обратите внимание на дату заметки – 2003 год). Так, быстро исправить ситуацию позволяет добавление заглушки в виде указателя, к примеру, на неиспользуемую целочисленную переменную, в качестве четвертого параметра на каждом вызове функции semctl().

На базе этой информации был составлен патч mpc85xx-fix.patch:

--- a/empty.c	2014-04-22 00:04:32.317542049 +0400
+++ b/empty.c	2014-04-22 00:06:02.580442807 +0400
@@ -177,6 +177,7 @@
 	int	fl_state = 2;		/* 0 - in	>>>
 					   1 - out	<<<
 					   2 - unknown */
+	int	dummy;
 	
 /* semaphores */
 #ifdef _POSIX_SEMAPHORES
@@ -495,7 +496,7 @@
 	
 	if (semop(sem, &free_sem, 1) == -1)
 		(void)perrxslog(255, "Can't release semaphore: %d from lock %m", sem);
-	if (semctl(sem, 0, IPC_RMID) == -1)
+	if (semctl(sem, 0, IPC_RMID, &dummy) == -1)
 		(void)syslog(LOG_NOTICE, "Warning: Can't remove semaphore: %d  %m", sem);
 
 #if !defined(__SVR4) && !defined(__hpux__) && !defined(__AIX)
@@ -779,7 +780,10 @@
 	va_end(va);
 	
 	if (sem != -1)
-		semctl(sem, 0, IPC_RMID);
+	{
+		int dummy;
+		semctl(sem, 0, IPC_RMID, &dummy);
+	}
 
 	(void)closelog();
 	(void)exit(ex_code);

Для использования его нужно разместить в папку ./package/feeds/packages/empty/patches относительно корня каталога buildroot'а OpenWrt и затем пересобрать утилиту командой make package/feeds/packages/empty/{clean,compile}.

Что характерно, проблема проявляется только при сборке под mpc85xx (powerpc), тогда как, к примеру, утилита, собранная для ar71xx (mips32r) работает корректно.

PS: Название утилиты empty обыгрывает сокращение pty, означающее "псевдотерминал", и слово "empty", означающее "пустоту". И все было бы хорошо, не будь "empty" до такой степени распространенным словом при описании той или иной компьютерной проблемы. В результате найти в интернете хоть какие-то обсуждения утилиты empty и с добавлением дополнительных ключевых слов вроде "terminal", "console" или "utility" терпят сокрушительное фиаско. По этой причине данную утилиту больше шансов найти по не совсем логичному названию empty-expect, что подчеркивает ее связь со значительно более известной утилитой автоматизации интерактивных консольных программ - expect.

Leave a Reply




*