Entry in if () but instructions are not executed

0

I am trying to make a chat using pipes (chat between server and client). I made an exit condition, in case the server wants to quit / disconnect the chat it writes "quit", in the client in the same way. Doing "quit" from the server is working, however from the client does not. My code is this:

client.c

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <ctype.h>
#include <pthread.h>
#include <string.h>
#include <fcntl.h>
#include "fifo.h"

int main()
{
    int readfd, writefd;
    umask(0);
    if((writefd=open(FIFO1, 1))<0)
        printf("client: Erro a abrir write fifo\n");
    if((readfd=open(FIFO2, 0))<0)
        printf("client: Erro ao abrir read fifo\n");

    char name[20], mensagem[200], OtherName[20];
    printf("Bem-vindo ao chat!\n");
    printf("Introduza o seu nome: ");
    fgets(name, 20, stdin);
    printf("Introduza quit caso deseja fechar o chat\n");

    if(fork()==0)
    {   
        while(1)
        {
            fgets(mensagem, 200, stdin);
            printf("\n");
            if(strncmp(mensagem, "quit", 4) == 0)
                exit(0);
            write(writefd, name, 20);
            write(writefd, mensagem, 200);
        }
    }

    else
    {
        while(1)
        {
            read(readfd, OtherName, 20);
            read(readfd, mensagem, 200);
            printf("\n%s -->%s\n", OtherName, mensagem);
        }
    }

    close(readfd);
    close(writefd);
    if(unlink(FIFO1)<0)
        printf("client: não foi possível fazer unlink\n");
    if(unlink(FIFO2)<0)
        printf("client: não foi possível fazer unlink\n");
    return 0;
}

server.c

#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <ctype.h>
#include <pthread.h>
#include <string.h>
#include <fcntl.h>
#include "fifo.h"

int main()
{
    int readfd, writefd;
    umask(0);
    unlink(FIFO1);
    unlink(FIFO2);//unlink dos fifos anteriores
    if((mknod(FIFO1, S_IFIFO | PERMS, 0))<0)
        printf("Erro a criar o fifo\n");
    if((mknod(FIFO2, S_IFIFO | PERMS, 0))<0)//criação de fifos
        printf("Erro a criar o fifo\n");
    if((readfd=open(FIFO1, 0))<0)//abrir o fifo em modo de leitura
        printf("Erro ao abrir read fifo\n");
    if((writefd=open(FIFO2, 1))<0)//abrir o fifo em modo de escrita
        printf("Erro ao abrir write fifo\n");

    char name[20], mensagem[200], OtherName[20];
    printf("Bem-vindo ao chat!\n");
    printf("Introduza o seu nome: ");
    fgets(name, 20, stdin);//nome do user no chat
    printf("Introduza quit caso deseja fechar o chat\n");

    if(fork()==0)//se fork()==0, então o server vai receber uma mensagem
    {   
        while(1)
        {
            read(readfd, OtherName, 20);//lê o nome do outro user
            read(readfd, mensagem, 200);//lê a mensagem do outro user
            printf("\n%s -->%s\n", OtherName, mensagem);//escreve a mensagem
        }
    }   

    else//se o servidor vai enviar uma mensagem
    {
        while(1)
        {
            fgets(mensagem, 200, stdin);//user introduz a mensagem
            printf("\n");
            if(strncmp(mensagem, "quit", 4) == 0)
                exit(0);
            write(writefd, name, 20);//escrever o nome para o pipe de escrita   
            write(writefd, mensagem, 200);//escrever a mensagem
        }
    }   

    close(readfd);
    close(writefd);     
    return 0;
}

In the client.c, do the following if:

if(strncmp(mensagem, "quit", 4) == 0)
 exit(0);

The program enters the if but does not execute instruction. Why does this happen? Thanks!

    
asked by anonymous 27.05.2017 / 22:25

1 answer

1

I made a minimal example:

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

int main()
{
  pid_t myPid = 0;

  if ((myPid = fork()) == 0)
    {
      printf ("processo pai %d\n", myPid);
      if (1)
        {
          exit(0);
        }
    }
  else
    {
      printf ("processo filho %d\n", myPid);
      while(1)
        {
          sleep(1);
          printf("mensagem do filho: dentro do while\n");
        }
    }

  return 0;
}

This example has the output:

macbook% ./a.out   
processo filho 2439
processo pai 0
mensagem do filho: dentro do while
mensagem do filho: dentro do while
mensagem do filho: dentro do while
^C
macbook% 

I found a answer in the OS. Here is the minimum example based on the response:

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/prctl.h>
#include <signal.h>

int main()
{

  // para testar o pid do pai apos o termino do pai
  pid_t ppid_before_fork = getpid();
  pid_t pid = fork();

  if (pid == -1)
    {
      perror(0);
      exit(1);
    }

  if (pid)
    {
      printf ("processo pai %d\n", pid);
      sleep(10);
      if (1)
        {
          exit(0);
        }
    }
  else
    {
      // do comando $ man prctl
      // Return  the current value of the parent process death signal, in
      //   the location pointed to by (int *) arg2.
      int r = prctl (PR_SET_PDEATHSIG, SIGTERM);
      printf ("processo filho %d\n", pid);
      while(1)
        {
          sleep(1);
          printf("mensagem do filho: dentro do while\n");
          // if que testa se o pid do pai esta diferente
          // ocorre apos o exit
          if (getppid() != ppid_before_fork)
            exit(1);
        }
    }

  return 0;
}

Basically, your colleague's example is based on the specification posix:

  

The parent process of the child processes and zombie processes of the calling process shall be set to the process of an implementation-defined system process. That is, these processes shall be inherited by a special process system.

With a quote from the response author:

  

Traditionally, the system process adopting all orphans is PID 1, i.e. init - which is the ancestor of all processes.

Briefly, the orphan process traditionally receives pid 1, as it is the ancestor of all processes.

One more quote from the author:

  

Note that storing the parent process id before the fork and testing it in the child after prctl () eliminates a race condition between prctl () and the exit of the process that called the child.

Storing the parent process before the fork and testing it after prctl () eliminates the race condition between prctl () and process output that calls the child.

ps1: $ man prctl info

  

This call is Linux-specific. IRIX has a prctl () system call (also introduced in Linux 2.1.44 as irix_prctl on the MIPS architecture), with prototype

It may not work on Unix

    
28.05.2017 / 01:29