Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Perl: Общие вопросы > Как гарантировано закрыть файл


Автор: Danissimo 6.12.2006, 17:11
Хочу, чтобы умирая (die или exit, или еще чего), программа из последних сил сбрасывала все файловые буферы. Как этого можно добиться.

Автор: Nab 6.12.2006, 17:16
Не буферизировать smile

Код

$| = 1;



Автор: Danissimo 6.12.2006, 17:21
Я делаю так:

autoflush $fileHandle TRUE;

Но не помогает, кажется. То есть я не вижу строк в логе. Хотя должны быть. Кажется. Короче говоря, зуб не дам, но грешу именно на то, что файл без флэша закрывается.

Автор: DiverD 6.12.2006, 17:41
select FH; 
$| = 1;

или 

select((select(FH), $|=1)[0]);

или

my $fh = select(FH);
$|++;
select($fh);

а autoflush эта в ОО, а так такой ф-ции нет.

еще глянь perldoc IO::File

Автор: Nab 6.12.2006, 17:44
Я не знаю как работает autoflush, но принцип таков: Если были буфера в которых осталась инфа, то при умирании они по любому теряються... 
Может спасти немедленная запись на диск, то есть без буферизации. 
Или делать это отдельным процессом, который будет поддерживать буффер открытым, и при умирании процесса сам будет его сбрасывать. 
Конечно тут возможен вариант аварийного завершения самого следящего процесса. Но здесь можно сделать взаимное слежение, и при умирании одного из пары, второй чтоб сбрасывал общий буфер в обязательном порядке. 
Конечно одновременное умирание двух процессов тоже возможно, но вероятность такого действа намного меньше smile Ну кроме толстой кнопки Reset, уборщицы со шваброй, и бестолкового электрика smile

Автор: Danissimo 8.12.2006, 09:54
Я тоже в этом направлении думаю. Тока не знаю, как реализовать. Более того, думаю, что скорее всего можно повесить какой-нть обработчик смерти, который не препятствует ей, но в последний момент все-таки просто-напросто говорит

close $fileHandle.

Мельком я видел, что можно повесить обрабочик на die. Но из-за мизерного опыта у меня нету уверенности, достаточно ли такого обработчика. Кроме того, возможно, что существует более толковое решение, чем обработчик die. Вобщем, моя проблема в том, что бъем информации большой, а опыта и времени у меня мало.

Автор: Nab 8.12.2006, 11:28
нет, при kill -9 обработчик не вызывается, это безоговорачная смерть smile

Автор: Danissimo 8.12.2006, 11:41
Ок. Если отказаться от внешних событий, приводящих к смерти, таких как kill -9 и швабра на рисете (вспомнилось: нет повести печальнее на свете, чем повесть о заклинившем рисете), то существует ли способ поймать момент, непосредственно перед самой смертью. Причем хочется поймать его после того, как все уже перестали писать в файл. В идеале -- последним. На практике -- после всех, кто может писать, но, возможно, перед теми, кто gracefully завершает перл.

Добавлено @ 11:43 
Хочу подчеркнуть, что автофлаш я уже включил. Но я почти (!)  уверен, что не все успевает записаться. То есть обработчик -- в дополнение к автофлашу, а не замена ему. Таким образом impact от kill -9 или заклинившего рисета минимизируется.

Автор: Nab 8.12.2006, 11:58
Упс, ну так я подозреваю, все остальные состояния перл сам вполне корректно обрабатывает, и закрывает хендлы...

Автор: Danissimo 8.12.2006, 12:35
Ок, в деталях.

Беру код. Много кода. Я знаю, какую он решает зачаду. Знаю общий принцип/алгоритм которым он ее решает. Но всех деталей не знаю. Например, я не знаю, а вешает ли он какие-нть подобные обработчики die.

Предположим, что вешает. Назовем, для определенности, этот самый обрабтчик именем А. Тогда мой обработчик (назовем его Б), закрывающий файл, должен выполняться после А, так как потенциально А может в процессе своего выполнения писать в файл. Как сделать так, чтобы мой Б выполнялся после всех возможных А?

Автор: Nab 8.12.2006, 12:42
вызывать внутри себя обработчик А а потом самому доделывать все остальные действия, и умирать при необходимости smile

Автор: Danissimo 8.12.2006, 12:55
Ха, так кода-то много =) И я не знаю, существует этот А или нет. Я изхожу из того, что возможно существует. Другими словами я хочу так прстроить программу, чтобы она делала все возможное в любом случае.

Если А существует, то Б будет вызываться после всех А. Если нет, то о4хор. Хуже не будет. Вызовется Б и все. Вопрос тока в том, возможно ли как-нть сделать так, чтобы Б вызывался после возможных А, о существовании которых я ничего не знаю, или не возможно.

Если невозможно, то я буду искать другие пути. Если возможно, то как.

Автор: Nab 8.12.2006, 13:07
приблизительно вот так:
Код

# сохраняем предыдущее состояние обработчика 
our $pre_interrupt = $SIG{__DIE__};
# вешаем свое
$SIG{__DIE__} = \&my_interrupt;

sub my_interrupt {
   # вызываем предыдужее
    &$pre_interrupt(@_);
   # ну а здесь делаем свои делишки
    ....
   # в конце желательно вызвать стандартный код перла
   CORE::die(@_);
}


Автор: Danissimo 8.12.2006, 13:19
Мега!!! То что надо! ЗАЧООООООООТ!!!!!!!!! Спасибо =))

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)