LINUX.ORG.RU

Блокировка файла (fcntl)


0

0

Блокировка файла (fcntl)

Язык СИ
ОС UNIX - Free-bsd

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

Вот тестовая программа:



#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <signal.h>

const char *f_test=«test»;
int fl_int=0, fd;


//---------------------- sigint -------------------------------------

void sigint(int n)
{
printf(«signal\n»);
//close(fd);
fl_int=1;
return;
}

//-------------------------- main -------------------------

int main()

{
int k;
pid_t pid;

fd=open(f_test,O_RDWR);
if(fd<0){ printf(«fd=open(%s)=%d\n»,f_test,fd); exit(0);}

pid=fork();
if(pid<0){ printf(«pid=fork()<0\n»); exit(0);}
if(pid==0){
signal(SIGINT, sigint);
sleep(5);
k=my_lock(fd,F_WRLCK);
printf(«k2=my_lock=%d\n»,k);
sleep(20);
exit(0);
}
if(pid>0){
k=my_lock(fd,F_WRLCK);
printf(«k1=my_lock=%d\n»,k);
sleep(10);
kill(pid, SIGINT);
sleep(10);
exit(0);
}
exit(0);
}


//------------------------------------- my_lock -----------------------------------

int my_lock(int fd,int cmd)

{
int k; struct flock lock;

lock.l_type=cmd;
lock.l_whence=SEEK_SET;
lock.l_start=0;
lock.l_len=0;
k=fcntl(fd,F_SETLKW,&lock);
return(k);
}


(Функция printf() запрещена в обработчиках сигналов,
но поскольку программа простая тестовая и от безысходности)
(состояние процессов удобно смотреть в другом окне утилитой top)


Эта программа не работает так, как я ожидал.

Ожидалось:
0 сек. -запуск программы, процесс (pid>0) блокирует файл;
5 сек. -процесс (pid==0) запрашивает блокировку файла и ждет её;
15 сек. -процесс (pid==0) получает сигнал, ожидание блокировки
прерывается. Вызов k=fcntl(fd,F_SETLKW,&lock); возвращает -1;

На самом деле работает так:
0 сек. -запуск программы, процесс (pid>0) блокирует файл;
5 сек. -процесс (pid==0) запрашивает блокировку файла и ждет её;
15 сек. -процесс (pid==0) прерывается сигналом
(обработчик пишет слово signal), и снова,
как ни в чем не бывало дожидает блокировку.
Дождавшись получает её.

fd -объявлен глобальным потому, что если раскомментировать строку
//close(fd);
в обработчике, то это выход из положения.

Хотелось бы понять почему не работает как задумано.
Кто знает прошу ответить.


Interruption of System Calls and Library Functions by Signal Handlers If a signal handler is invoked while a system call or library function call is blocked, then either:

* the call is automatically restarted after the signal handler returns;
or

* the call fails with the error EINTR.

Which of these two behaviors occurs depends on the interface and whether or not the signal handler was established using the SA_RESTART flag (see sigaction(2)). The details vary across Unix systems; below, the details for Linux.

If a blocked call to one of the following interfaces is interrupted by a signal handler, then the call will be automatically restarted after the signal handler returns if the SA_RESTART flag was used; otherwise the call will fail with the error EINTR:

...

* File locking interfaces: flock(2) and fcntl(2) F_SETLKW.

...

gena2x ★★★
()
Ответ на: комментарий от gena2x

Да.
Это работает.
Со сброшенным флагом SA_RESTART.

Спасибо.

oleg_2
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.