Thank you for reading this, I appreciate a lot!
I have this part of code:
for(i=0;i<n;i++)
{
printf("dopo %d sec ricevuto kill\n",20-sleep(20));
kill( pidFiglio[i],SIGKILL);
}
for (i=0 ; i<n ; i++)
{
//attesa della terminazione di un processo figlio
pidDaWait = wait( & status );
//(...)
but i can't understand why the father process is able to wait his sons, after he killed them!
The kill function returns 0 so it works, but the father is able to wait "his sons" after.
I know that it's a stupid answer, but I'm absolutely new in multiprogramming.
#include <stdio.h>
#include <stdlib.h> //per la exit()
#include <unistd.h> //per la fork()
#include <sys/types.h> //per la wait()
#include <sys/wait.h> //per la wait()
#include <signal.h> //per la signal()
int contSigusr1;
void trapSIGUSR1(int nsignal);
int main( int argc , char* argv[] )
{
int i;
int n;
pid_t pidFiglio[10];
pid_t pidDaWait;
int status;
contSigusr1=0;
signal ( SIGUSR1, trapSIGUSR1 );
printf("argc = %d\n", argc);
if ( argc < 3 )
{
printf("Sintassi errata!\n");
printf("il programma termina con errore\n");
exit(1);
}
n = atoi( argv[1] );
for (i=0; i<n; i++)
{
pidFiglio[i] = fork();
if ( pidFiglio[i] == 0 )
{
printf("Figlio - getpid = %d\n", getpid());
printf("Figlio - getppid = %d\n", getppid());
printf("(%d)%s\n",getpid(),argv[2+i]);
sleep(i*5);
kill( getppid() , SIGUSR1);
sleep(i+1*5);
printf("Figlio - termina correttamente\n");
exit(0);
}
}
printf("getpid = %d\n", getpid());
printf("getppid = %d\n",getppid());
for(i=0;i<n;i++)
{
printf("dopo %d sec ricevuto kill\n",20-sleep(20));
kill( pidFiglio[i],SIGKILL);
}
for (i=0 ; i<n ; i++)
{
pidDaWait = wait( & status );
printf("status = %d\n", status);
printf("status di (%d) con WEXITSTATUS = %d\n",
pidDaWait,
WEXITSTATUS( status));
if ( WIFSIGNALED (status) )
printf("il processo figlio (%d) e` terminato tramite un segnale\n",pidDaWait);
else
printf("il processo figlio (%d) e` terminato normalmente\n",pidDaWait);
}
printf("il padre termina dopo la terminazione del processo figlio con pid = %d\n",pidDaWait );
exit(0);
}
void trapSIGUSR1(int nsignal)
{
contSigusr1= contSigusr1 +1;
printf("riceived %d SIGUSR1 = %d\n",nsignal,contSigusr1);
}
Just don't pay attention to the italian words :D
Thank you in advance,
Have a good day!
Childs still exist, but are now zombies.
Childs may terminate their execution, but the task_struct still exists in kernel. The task_struct in kernel holds the return status information from the child (and some other info). The zombie task_struct exists only so that the parent process may get the child return status (via wait(&status) + WEXITSTATUS(status)) and other information about the child, so that parent code may be consistent.
Sending SIGKILL to children or terminating all children using exit() call (like in wikipedia) does not matter - the result is that the child process becomes a zombie. After the parent calls wait and that wait services that child, it's task_struct from kernel get's freed and the status information get's returned to the parent, so he can handle it.
Related
I have a project where I need to create N child processes and to do an election between them. So I've made so far a function to generate the random number (for the election, they have to compare the number they were attributed then the lower number is elected). Then, I'm stuck to make them communicate with pipes to compare the number. My problem is that only my first child process run the end of this for loop I really don't understand why. Here's all of my code so far :
void comparerIdElection(int (*pipes)[2], int numProc)
{
for (int i = 0; i < NBPROC; ++i)
{
if (numProc!=i)
{
close(pipes[i][0]);
printf("je suis %d et je ferme la pipe [%d][0]\n",getpid(),i );
}else printf("je suis %d et je laisse la pipe [%d][0] \n",getpid(),i );
if (numProc +1 != i)
{
close(pipes[i][1]);
printf("je suis %d et je ferme la pipe [%d][1]\n",getpid(),i );
}else printf("je suis %d et je laisse la pipe [%d][1] \n",getpid(),i );
}
//Generate a random number for my child process
int GenererIdElection ()
{
srand(time(NULL)^getpid()<<16);
return rand()%NBPROC;
}
int main(int argc, char const *argv[])
{
int N = NBPROC, idElection, numProc= -1;
int pere = getpid();
/*Creation du nombre de pipe adequat */
int pipes[N][2];
int pids[N];
/* Indique l'etat du processus C = Candidat, B =B battu , E = Elu*/
char etat ;
printf("le nombre de processus que je crée est : %d\n", N);
// Creation d'un nombre de N processus fils par le même pere
for (int i = 0; i < N; ++i)
{
if(getpid()==pere){
fork() ;
numProc ++ ;
}
}
if (getpid() != pere)
{
pids[numProc] = getpid();
etat = 'C';
while(etat == 67)
{
idElection = GenererIdElection();
printf("je suis %d et j'ai eu %d, mon num proc est %d \n",getpid(), idElection, numProc);
comparerIdElection(pipes, numProc);
printf("hop\n");
etat ='B';
}
}
if (getpid()==pere)
{
/*On attend la fin de chaque processus
pour mettre un terme au processu pere*/
for (int i = 0; i < N; ++i)
{
wait(&pids[i]);
}
}
exit(0);
}
And here is what happens once executed (I translated all of printf) :
[terminal][1]
Edit : As I can't post image due to a lack of reputation I copy/pasta :
I'm 1854 i got 1, my numproc is : 0
I'm 1854 i don't close pipe [0][0]
I'm 1854 i close [0][1]
I'm 1854 i close pipe [1][0]
I'm 1854 i don't close pipe [1][1]
I'm 1854 i close pipe [2][0]
I'm 1854 i close [2][1]
hop
I'm 1855 i got 1, my numproc is : 1
I'm 1855 i close pipe [0][0]
I'm 1855 i close [0][1]
I'm 1855 i don't close pipe [1][0]
I'm 1856 i got 1, my numproc is : 2
I'm 1856 i close pipe [0][0]
I'm 1856 i close [0][1]
I'm 1856 i close pipe [1][0]
NB : NBPROC = 3 in this case, but no matter the Number of value it does not work except for the very first child processes.
I seem to have a plausible explanation for the behavior of your program. As I've already pointed out in the comments, there is an obvious flaw in the program that the int pipes[N][2]; weren't set up which would end up in the close() APIs actually just leading to EBADF being returned and probably not achieving what had been intended.
As for your program's behavior, that can be explained by inspecting the actual values being populated in the array int pipes[N][2];. Since the values aren't being set explicitly in the original question, the values are essentially undefined but...
Let's try setting them to something more sane values using:
int pipeVal = INT32_MIN;
if(argc == 2) {
pipeVal = atoi(argv[1]);
}
for(int i = 0; i < N; ++i) {
if(pipeVal != INT32_MIN) {
pipes[i][0] = pipes[i][1] = pipeVal;
}
printf("%d: Pipe pair %d-%d\n",getpid(), pipes[i][0], pipes[i][1]);
}
Passing in 0 yields the output:
61962: Number of process is : 3
61962: Pipe pair 0-0
61962: Pipe pair 0-0
61962: Pipe pair 0-0
61963: Election Id 0, numProc 0
61963: Exiting while-loop
61964: Election Id 0, numProc 1
61964: Exiting while-loop
61965: Election Id 0, numProc 2
61965: Exiting while-loop
This seems to align with what's expected: fork 3 processes which just exit eventually. Let's try with the value of 1
62033: Number of process is : 3
62033: Pipe pair 1-1
62033: Pipe pair 1-1
62033: Pipe pair 1-1
62034: Election Id 0, numProc 0
62035: Election Id 2, numProc 1
62036: Election Id 0, numProc 2
Now this appears to be weird since none of the processes actually exit out of the while loop, yet the main program terminates successfully. To actually check the exit status of the child programs, I added the following code:
if (getpid()==pere)
{
/*On attend la fin de chaque processus
pour mettre un terme au processu pere*/
for (int i = 0; i < N; ++i)
{
errno = 0;
int stat_val;
wait(&stat_val);
#if DBG == 1
printf("%d: WIFEXITED(%d),WEXITSTATUS(%d),WIFSIGNALED(%d),WTERMSIG(%d),WIFSTOPPED(%d),WSTOPSIG(%d),WIFCONTINUED(%d)\n", getpid(), WIFEXITED(stat_val),WEXITSTATUS(stat_val),WIFSIGNALED(stat_val),WTERMSIG(stat_val),WIFSTOPPED(stat_val),WSTOPSIG(stat_val),WIFCONTINUED(stat_val));
#endif
}
}
Here's the output on passing in 1 as the argument:
62215: WIFEXITED(1),WEXITSTATUS(0),WIFSIGNALED(0),WTERMSIG(0),WIFSTOPPED(0),WSTOPSIG(0),WIFCONTINUED(0)
62215: WIFEXITED(1),WEXITSTATUS(0),WIFSIGNALED(0),WTERMSIG(0),WIFSTOPPED(0),WSTOPSIG(0),WIFCONTINUED(0)
62215: WIFEXITED(1),WEXITSTATUS(0),WIFSIGNALED(0),WTERMSIG(0),WIFSTOPPED(0),WSTOPSIG(0),WIFCONTINUED(0)
This output indicates that all the processes exited normally without being stopped abnormally by any signal whatsoever.
The clue is in the actual fds these processes are trying to close. In Linux (at least) a process once created has 3 file descriptors 0 for stdin, 1 for stdout, and 2 for stderr. When 0 is passed as an argument to the program, the processes just end up closing stdin (close(0)) which isn't being used anyway, hence no issues, and they exit comparerIdElection() and the while-loop subsequently. When 1 is passed in as a parameter to the program, the processes end up closing stdout (close(1)), hence whatever is supposed to be written to the output is not seen on the console anymore, yet they still do exit comparerIdElection() and the while-loop subsequently and thus the WIFEXITED(1) from each process.
Now coming to the actual program shared, what are the actual values that end up getting populated is unspecified, but if even one of the N*2 fds in the array is set to 1, the behavior as above (passing in 1) shall be exhibited i.e. even though the printfs won't be written to the console, the processes do actually exit the while-loop and the main parent process is successfully able to wait for the processes. On my PC (and I suspect on yours too), the actual value of at least one of those array elements is always set to 1.
Values of pipe fd pairs on my Mac:
61120: Pipe pair -296602944-32766
61120: Pipe pair 23978080-1
61120: Pipe pair 64-0
Their values on TryItOnline:
25090: Pipe pair 0-0
25090: Pipe pair 68079952-32708
25090: Pipe pair 1-0
Their values on OnlineGDB (need to add the compiler flag -DNBPROC=3):
5612: Pipe pair 1505064448-32611
5612: Pipe pair 1507242440-32611
5612: Pipe pair 1-0
This analysis should hold irrespective of the value of NBPROC since till there's 1 amongst the pipe fds, that process will end up closing its own stdout and exhibit similar behavior.
Here's the complete program with some instrumentation that can be enabled by passing in DBG=1 and some PID-tagging to figure out which process is the log from :
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
#include <sys/wait.h>
#include <errno.h>
#include <string.h>
#include <stdint.h>
void comparerIdElection(int (*pipes)[2], int numProc)
{
for (int i = 0; i < NBPROC; ++i)
{
if (numProc!=i)
{
#if DBG == 1
printf("%d: Before close pipe [%d][0](%d)\n",getpid(),i , pipes[i][0]);
#endif
errno = 0;
close(pipes[i][0]);
#if DBG
printf("%d: closed pipe [%d][0](%d) %s\n",getpid(),i, pipes[i][0], strerror(errno));
#endif
} else {
#if DBG == 1
printf("%d: no action on pipe [%d][0](%d) \n",getpid(),i, pipes[i][0] );
#endif
}
if (numProc +1 != i)
{
#if DBG == 1
printf("%d: Before close pipe [%d][1](%d)\n",getpid(),i, pipes[i][1] );
#endif
errno = 0;
close(pipes[i][1]);
#if DBG == 1
printf("%d: close pipe [%d][1](%d) %s\n",getpid(),i, pipes[i][1], strerror(errno) );
#endif
} else {
#if DBG == 1
printf("%d: no action pipe [%d][1](%d) \n",getpid(),i, pipes[i][1] );
#endif
}
}
}
//Generate a random number for my child process
int GenererIdElection ()
{
srand(time(NULL)^getpid()<<16);
return rand()%NBPROC;
}
int main(int argc, char const *argv[])
{
int N = NBPROC, idElection, numProc= -1;
int pere = getpid();
int pipes[N][2];
int pids[N];
char etat ;
printf("%d: Number of process is : %d\n", getpid(), N);
int pipeVal = INT32_MIN;
if(argc == 2) {
pipeVal = atoi(argv[1]);
}
for(int i = 0; i < N; ++i) {
if(pipeVal != INT32_MIN) {
pipes[i][0] = pipes[i][1] = pipeVal;
}
printf("%d: Pipe pair %d-%d\n",getpid(), pipes[i][0], pipes[i][1]);
}
for (int i = 0; i < N; ++i)
{
if(getpid()==pere){
pid_t pid = fork() ;
numProc++;
if(pid == 0) {
// sleep(10);
#if DBG == 1
printf("%d: After fork in the child got fork-pid %d\n", getpid(), pid);
#endif
} else {
pids[numProc] = pid;
#if DBG == 1
printf("%d: After fork in the parent got fork-pid %d numProc %d pids[%d] = %d\n",
getpid(), pid, numProc, numProc, pids[numProc]);
#endif
}
}
}
if (getpid() != pere)
{
etat = 'C';
while(etat == 67)
{
idElection = GenererIdElection();
printf("%d: Election Id %d, numProc %d \n",getpid(), idElection, numProc);
comparerIdElection(pipes, numProc);
etat ='B';
}
printf("%d: Exiting while-loop\n", getpid());
}
if (getpid()==pere)
{
/*On attend la fin de chaque processus
pour mettre un terme au processu pere*/
for (int i = 0; i < N; ++i)
{
errno = 0;
int stat_val;
wait(&stat_val);
#if DBG == 1
printf("%d: WIFEXITED(%d),WEXITSTATUS(%d),WIFSIGNALED(%d),WTERMSIG(%d),WIFSTOPPED(%d),WSTOPSIG(%d),WIFCONTINUED(%d)\n", getpid(), WIFEXITED(stat_val),WEXITSTATUS(stat_val),WIFSIGNALED(stat_val),WTERMSIG(stat_val),WIFSTOPPED(stat_val),WSTOPSIG(stat_val),WIFCONTINUED(stat_val));
#endif
}
}
printf("%d: Exiting process\n", getpid());
exit(EXIT_SUCCESS);
}
I want to make the parent processes (P1 and P2) wait for their respective child processes(P3 and P4) to terminate using waitpid (basically, parent processes can only terminate after the children terminates). Here's the code below. I'm portuguese, sorry for having non-english words on the code.
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
int main()
{
int estado1, estado2;
pid_t p = fork();
pid_t k = fork();
if(p>0) //Execução do pai
{
waitpid(p, &estado1, 0); //Don't know how waitpid works that well either
waitpid(k, &estado2, 0);
printf("p=%d: PID = %d;\t", p, getpid());
// \t é para dar um tab (o que se usa nas indentações)
sleep(45);
printf("O processo pai terminou.\n");
exit(0);
}
else if(p==0) //Execução do filho
{
printf("p=%d: PID = %d;\t", p, getpid());
// \t é para dar um tab (o que se usa nas indentações)
printf("O processo filho terminou.\n");
exit(0);
}
else if(p<0)
{
printf("ERRO! p=%d\n", p);
exit(p);
}
}
This is what I have but I think it isn't right.
Thanks in advance.
Edit: Thanks to zeroSpook for fixing my text :)
I want create a son(1) with fork() and this son needs to create another son(2).
son (1) and father needs to wait for their son's end gives a info. I want all of them to printf their PID.
This is my code:
#include <stdio.h>
#include <stdlib.h>
int main(){
int pid; //i know thats not good
if((pid = fork ()) == 0) { //this isnt good either
printf ("SON %d\n",getpid());
} else {
// sleep(1) not necessary
printf ("Thats the Father\n");
printf ("PID of my Son PID %d\n",pid);
}
}
Found several infos to create multiple children out of 1 father but I don't know, how to create a new child out of a child.
Found several infos to create multiple childs out of 1 father but i dont know, how to create a new child out of a child.
It's exactly like how you create the first child process. You need to fork() again in the child process to create another process. Use wait(2) to wait for the child processes.
Consider the example (with no error checking):
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(void){
pid_t pid;
if((pid = fork()) == 0) {
printf ("Child process: %d\n", (int)getpid());
pid_t pid2;
if ((pid2 = fork()) == 0) {
printf("Child's child process: %d\n", (int)getpid());
} else {
int st2;
wait(&st2);
}
} else {
printf ("Parent process: %d\n", (int)getpid());
int st;
wait(&st);
}
return 0;
}
Thanks for the great response. Got it know.
my actual code:
#include <stdio.h>
#include <stdlib.h>
int main(void){
int pid;
int pid2;
int st;
int st2;
if((pid = fork()) == 0) {
printf ("Kind: %d\n",getpid());
if ((pid2 = fork()) == 0) {
printf("Kindes Kind process: %d\n",getpid());
} else {
wait(&st2);
}
} else {
printf("Ich warte auf meinen Sohn\n"); //WAITING FOR MY SON
wait(&st);
printf("mein Sohn ist fertig\n"); // MY SON IS RDY
printf ("Vater process: %d\n", getpid());
printf("Vater: Status = %d\n",st); //MY STATUS AS A FATHER
}
return 0;
}
My outcome:
Ich warte auf meinen Sohn //waiting for my son
Kind: 2175 //pid children
Kindes Kind process: 2176 // childrens child pid
mein Sohn ist fertig //my son finished
Vater process: 2174 //father pid
Vater: Status = 0 //father status
My only problem is, that the PID of the first child prints out first.
I want the child to wait for his own child and the prints out his own pid.
Like:
waiting for my Son(2)
pidchild2
my son2 finished
status
waiting for my son
pidchild1
my son1 finished
father pid
status
edit:
got it, i think
just had to printf beyond the wait2. was obvious
#include <stdio.h>
#include <stdlib.h>
int main(void){
int pid;
int pid2;
int st;
int st2;
if((pid = fork()) == 0) {
if ((pid2 = fork()) == 0) {
printf("Kindes Kind process: %d\n",getpid());
} else {
printf("Ich warte auf meinen Sohn1\n");
wait(&st2);
printf("mein Sohn ist fertig2\n"); // MY SON IS RDY
printf ("Kind: %d\n",getpid());
printf("Sohn1: Status = %d\n",st2); //MY STATUS AS A FATHER
}
} else {
printf("Ich warte auf meinen Sohn\n"); //WAITING FOR MY SON
wait(&st);
printf("mein Sohn ist fertig\n"); // MY SON IS RDY
printf ("Vater process: %d\n", getpid());
printf("Vater: Status = %d\n",st); //MY STATUS AS A FATHER
}
return 0;
}
I'm trying to make a main process wait for the completion of the process instructed by waitpid, but right on the call to waitpid, an infinite loop occurs.
It seems that the process referenced by waitpid never ends.
This process is always an execlp to unix command, as wc, rev, cat ...
If I comment the code concerning waitpid, unix command ends perfectly.
Deputy code for the call to the mandate and the wait:
int pid;
int estado_proceso;
for(pid=0;pid<numFiltros;pid++)
{
fprintf(stderr,"A esperar a %d\n", pids[pid]);
if (waitpid(pids[pid],&estado_proceso,0) >= 0)
imprimir_estado(filtros[pid], estado_proceso);
else
{
fprintf(stderr,"Error al esperar proceso %d\n",pid);
exit(1);
}
}
fprintf(stderr,"A ejecutar comando \n");
execlp(filtro,filtro, NULL);
fprintf(stderr,"Error al ejecutar el mandato '%s'\n",filtro);
exit(1);
Edit:
Fork and Pid obtain code:
switch(pid = fork())
{
/* Error en el Fork */
case -1:
fprintf (stderr,"Error al crear proceso %d\n", pid);
exit(1);
/* Father Process*/
default:
pids[i-1] = pid;
On Main:
pids = (pid_t*) malloc (sizeof(pid_t)*numFiltros);
Where "numFiltros" is the number of unix commands like wc, cat, rev...
Any idea?
Thanks a lot!
Try using wait instead of explicit waitpid, that is, try replacing your waiting code with
int pid;
int estado_proceso;
while((pid = wait(&estado_proceso)) >= 0) {
if(pid > 0) {
fprintf(stderr, "Process with PID %d terminated.\n", pid);
imprimir_estado(pid, estado_proceso);
}
}
I need to properly handle EDEADLK. In my program I see that both children wait until parent sleep and, and then they apply the lock and right away they leave it. Sorry for my mistakes, I am a Spanish student.
int main(){
pid_t childpid, childpid2;
struct flock cerrojo;
int fd, status;
if ((fd=open("prueba", O_RDWR)) == -1)
perror("apertura fallo");
cerrojo.l_type =F_WRLCK;
cerrojo.l_whence =SEEK_SET;
cerrojo.l_start =0;
cerrojo.l_len =0;
if (fcntl(fd, F_SETLK,&cerrojo) == -1)
perror("cerrojo fallo");
if ((childpid= fork()) == -1) {
printf("Could not create child");
exit(-1);
}
if(childpid){
if ((childpid2= fork()) == -1) {
printf("Could not create child");
exit(-1);
}
if(childpid2){
cerrojo.l_type = F_UNLCK;
cerrojo.l_whence =SEEK_SET;
cerrojo.l_start =0;
cerrojo.l_len =0;
sleep(2);
fcntl(fd, F_SETLKW, &cerrojo);
waitpid(childpid,&status,0);
waitpid(childpid2,&status,0);
}
}
if(!childpid||!childpid2){
printf("Soy el hijo %d\n",getpid());
if(fcntl(fd, F_SETLKW,&cerrojo) == -1){
printf("FCNTL FALLA EN PID: %d\n",getpid());
sleep(1);
}
printf("PID %d va a quitar el cerrojo.\n",getpid());
cerrojo.l_type = F_UNLCK;
cerrojo.l_whence =SEEK_SET;
cerrojo.l_start =0;
cerrojo.l_len =0;
fcntl(fd, F_SETLKW, &cerrojo);
printf("HIJO ACABADO\n");
}
return 0;
}
For deadlock you need at least two locks. I always imagine myself locked in room A, with the key of room B, and someone else in room B, with the key of room A.
In your example there is only one lock: both children try to lock the same big "door" (the whole file). The second who gets there will block until the first releases the lock again, and then sing the same litle song Lock, sleep,... unlock. No deadlock in sight.
Now, in the example below, the parent locks two "doors" - the first and second byte of the file fd points to (btw, is this really necessary for your example?) and then spawns two children. Both children try to lock both bytes, but each begins with a different one. As soon as the parent releases both bytes the children acquire their locks, 4 lock attempts in all, but the last one would cause deadlock, and duly fails with EDEADLK, so that everybody lives happily ever after - thanks to our wise and just kernel.
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int main(){
pid_t childpid, childpid2;
struct flock cerrojo;
int fd, status;
if ((fd=open("prueba", O_RDWR)) == -1)
perror("apertura fallo");
cerrojo.l_type = F_WRLCK;
cerrojo.l_whence = SEEK_SET;
cerrojo.l_start = 0;
cerrojo.l_len = 2; /* lock "doors" (i.e. bytes) 0 and 1*/
if (fcntl(fd, F_SETLK,&cerrojo) == -1)
perror("cerrojo fallo");
if((childpid= fork())){ /* parent */
if ((childpid2= fork())) { /* still parent */
cerrojo.l_type = F_UNLCK;
cerrojo.l_len = 2; /* unlock both doors: let the fun begin :-) */
sleep(2);
printf("Tata va a quitar el cerrojo....\n",getpid());
fcntl(fd, F_SETLKW, &cerrojo);
waitpid(childpid,&status,0);
waitpid(childpid2,&status,0);
}
}
if(!childpid||!childpid2){ /* in child 1 or child 2 */
printf("Soy el hijo %d\n",getpid());
int offset0 = (childpid ? 0 : 1); /* child1 gets 0 and 1, child 2 gets 1 and 0 */
int offset1 = (childpid ? 1 : 0);
cerrojo.l_len = 1;
cerrojo.l_start = offset0; /* lock door 0 (1) as soon as parent lets us*/
printf("PID %d locking byte %d\n", getpid(), offset0);
if(fcntl(fd, F_SETLKW,&cerrojo) == -1){
printf("CERROJO byte %d FALLA EN PID %d (%s)\n",offset0, getpid(), strerror(errno));
}
sleep(1); /* guarantee that the other child has our next door locked ... */
printf("PID %d locking byte %d\n", getpid(), offset1);
cerrojo.l_start = offset1; /* lock door 1 (0). The second of both children who gets here closes the circle and faces deadlock */
if(fcntl(fd, F_SETLKW,&cerrojo) == -1){
printf("CERROJO byte %d FALLA EN PID: %d (%s)\n", offset1, getpid(), strerror(errno));
}
printf("HIJO %d ACABADO (releasing its lock)\n", getpid()); /* Falling off the end of main() will release the lock anyway */
}
}
The output:
[hlub#karpaten] ~ > ./test
Soy el hijo 29711
PID 29711 locking byte 1
Soy el hijo 29712
PID 29712 locking byte 0
Tata va a quitar el cerrojo....
PID 29711 locking byte 0
PID 29712 locking byte 1
CERROJO byte 1 FALLA EN PID: 29712 (Resource deadlock avoided)
HIJO 29712 ACABADO (releasing its lock)
HIJO 29711 ACABADO (releasing its lock)