SIGALRM, докато спя на Solaris 9

Попадам на малко странна грешка, докато изпълнявам Perl в chroot среда на Solaris 9 (Sparc). Ние използваме персонализиран Perl, но това е почти точно Perl 5.8.7 и тази версия работи от години на различни платформи, включително Solaris 8-10.

Следният код е доста ясен:

#!/usr/bin/perl
use strict; 
use warnings;

print "About to sleep(1)\n";
sleep 1;
print "Just woke up!\n";

Въпреки това, ако стартирам това, "Току-що се събудих!" никога не се отпечатва - вместо това програмата приключва и на екрана се повтаря "Будилник". Това се случва само ако има заспиване - ако напиша програма, която прави много математика и отнема 10 секунди за изпълнение, всичко работи добре. Също така се случва само в chroot среда.

Изхвърлих %SIG, който има запис 'ALRM => undef', което се очаква - средата без chroot има същото поведение. Ако обаче променя скрипта, за да включва:

$SIG{ALRM} = sub {};

... всичко работи добре. И така, каква е сделката? Нямам много опит със Solaris, но трябва да има начин манипулаторите на сигнали по подразбиране да се държат правилно.


person Chris Simmons    schedule 06.07.2009    source източник


Отговори (3)


Първото нещо, което бих опитал е да изпълня вашата примерна програма под ферма:

truss testprogram.pl

Това ще покаже действителните системни повиквания, използвани за изпълнение на заспиването. В система Solaris 8, до която имам достъп, съответната част от изхода е:

write(1, " A b o u t   t o   s l e".., 18)      = 18
time()                                          = 1247258429
alarm(0)                                        = 0
sigaction(SIGALRM, 0xFFBEF6E0, 0xFFBEF790)      = 0
sigfillset(0xFF0C28D0)                          = 0
sigprocmask(SIG_BLOCK, 0xFFBEF780, 0xFFBEF770)  = 0
alarm(1)                                        = 0
    Received signal #14, SIGALRM, in sigsuspend() [caught]
sigsuspend(0xFFBEF760)                          Err#4 EINTR
setcontext(0xFFBEF448)
alarm(0)                                        = 0
sigprocmask(SIG_UNBLOCK, 0xFFBEF780, 0x00000000) = 0
sigaction(SIGALRM, 0xFFBEF6E0, 0x00000000)      = 0
time()                                          = 1247258430
Just woke up!
write(1, " J u s t   w o k e   u p".., 14)      = 14

На хост Solaris 10 той извежда:

write(1, " A b o u t   t o   s l e".., 18)      = 18
time()                                          = 1247258270
nanosleep(0xFFBFF770, 0xFFBFF768)               = 0
time()                                          = 1247258271
Just woke up!
write(1, " J u s t   w o k e   u p".., 14)      = 14

Предполагам, че ще получите нещо по-близо до изхода на Solaris 8 и вероятно ще покаже извикването на sigaction() неуспешно по някаква причина.

Освен това, бих проверил дали споделените библиотеки в chroot /usr/lib всъщност са правилните версии за хоста и версията на ОС. Изходът на фермата също ще ви покаже точно кои споделени библиотеки се зареждат от perl.

person Kenster    schedule 10.07.2009
comment
Хм.. Можех да се закълна, че имах truss, работещ преди, но това ме притеснява: getexecname() се провали сега. Ще разгледам това. Благодаря! - person Chris Simmons; 15.07.2009
comment
Да, като се замисля, може да е трудно да накарате truss да работи в chroot средата. Можете да стартирате truss извън средата, или като използвате опцията -p за свързване на PID, или чрез truss chroot: команда truss chroot /newroot - person Kenster; 15.07.2009
comment
Приемането на този отговор като работеща ферма и разследването защо се провали ме накара да открия това, което според мен беше истинският проблем - операционната система беше странен хибрид на Solaris 9 с библиотеки на Solaris 8. Повторното инсталиране на операционната система правилно коригира тези проблеми. - person Chris Simmons; 03.08.2009

Препоръчвам просто да замените sleep 1 повикванията с select(undef, undef, undef, 1) и да избегнете целия проблем.

От симптомите, които давате, бих се обзаложил, че вашият chroot'd perl скрипт прилага sleep по отношение на SIGALRM (както е разрешено от POSIX) и че по някаква причина perl не улавя този сигнал както трябва, може би защото не очаква това изпълнение. Това вашата персонализирана компилация на perl ли е? Дали това е идиосинкразия в chroot'd libc? perl -e "sleep 1" под chroot показва ли същия проблем? И т.н. и т.н. Трудно е да се каже без достъп до околната среда и инструмент като опора.

Отново, целият проблем може да бъде избегнат: select няма да бърка с SIGALRM.

person pilcrow    schedule 06.07.2009
comment
За съжаление не мога да направя това - имам работа с много голяма кодова база, която работи на множество платформи. Не променям всичко само за Solaris 9 :) Стандартът POSIX, който споменавате, е много вероятно случаят. Почти съм сигурен, че моята компилация на perl не се забърква с това, но може да е libc версията на chroot. Благодаря :) - person Chris Simmons; 06.07.2009
comment

Добре, признавам, че съм нов в LINQ и прекарах последната седмица в четене на всичко, което можах за него. Просто си играя, опитвайки се да следвам някои примери, които намерих (всъщност PDF от Скот Гу по темата) и съм напълно загубен. Може ли някой да ми каже защо, когато свържа GridView със заявката по-долу, използвайки кода по-долу, не получавам данни?? Мога да видя резултатите, докато отстранявам грешки, така че знам, че се връщат от DB, просто очевидно не се свързват правилно. Прочетох нещо, което казва, че не можете да се свържете директно с резултата и че трябва да използвате BindingSource като междинна стъпка?

Някой, моля, кажете ми какво пропускам тук.

protected void Page_Load(object sender, EventArgs e)
{
    SwapDBDataContext db = new SwapDBDataContext();

    var users = from u in db.aspnet_Users
                select new
                {
                   Name =  u.UserName,
                   ID = u.UserId
                };

    GridView1.DataSource = users;
    GridView1.DataBind();

}

Просто използвам празен GridView. Бях предположил, че обвързването ще се погрижи за настройването на колоните, за да съответстват на получените колони от заявката - това глупава грешка за начинаещи ли беше?

    <asp:GridView ID="GridView1" runat="server">
    </asp:GridView>
- person Chris Simmons; 06.07.2009
comment
Ако не е ясно, мисля, че всички се радваме, че имате версия на Perl с грешка. ;-) - person ijw; 07.07.2009
comment
Това в момента е оставено на заден план, но се надявам, че ще се опитам да получа актуализация за него в рамките на седмица или повече. Благодаря на всички за помощта досега. - person Chris Simmons; 15.07.2009

Имате ли все още версията на Perl, която идва със Solaris? Ако е така, опитайте кода си върху него. Ако нямате тази версия, предлагам да изтеглите Perl 5.8.7, компилиране на стандартна версия и след това тестване на вашия скрипт върху нея.

Ако вашият скрипт работи правилно на някоя от тези две версии, тогава знаете, че проблемът е свързан с промените във вашата версия на Perl. Ако скриптът има същата грешка, тогава бих предложил да изтеглите Perl 5.8.9, като го компилира и след това проверява дали грешката изчезва. Ако не стане, поздравления, открили сте грешка в Perl. Вероятно ще искате да стартирате perlbug, за да го докладвате.

person Chas. Owens    schedule 06.07.2009