Januszoff
Januszoff

Reputation: 315

Using pipes to send strings between processes

I'm trying to rewrite my code from C# to C and have a bit of a trouble.

So I have a file, named test, in which there is a single line of text. I want to read that line, send it through pipe between processes and print it on screen.

Here's the code:

    #include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>


void
read_from_pipe (int file)
{
  FILE *stream;
  int c;
  stream = fdopen (file, "r");
  while ((c = fgetc (stream)) != EOF)
    putchar (c);
  fclose (stream);
}

void
write_to_pipe (int file)
{
  FILE *stream;
  FILE *testfile;
  stream = fdopen (file, "w");
  testfile = fopen("test.txt", "r");
  char *line = NULL;
  size_t len = 0;
  //ssize_t read;
  getline(&line, &len, testfile);
  fprintf (stream, "%s", line);
  free(line);
  fclose(testfile);
  fclose (stream);
}

int
main (void)
{
  pid_t pid;
  int mypipe[2];


  if (pipe (mypipe))
    {
      fprintf (stderr, "Pipe failed.\n");
      return EXIT_FAILURE;
    }
  pid = fork ();
  if (pid == (pid_t) 0)
    {
      close (mypipe[1]);
      read_from_pipe (mypipe[0]);
      return EXIT_SUCCESS;
    }
  else if (pid < (pid_t) 0)
    {
      fprintf (stderr, "Fork failed.\n");
      return EXIT_FAILURE;
    }
  else
    {
      close (mypipe[0]);
      write_to_pipe (mypipe[1]);
      return EXIT_SUCCESS;
    }
}

However I seem to be getting segmentation error while running this code. Is there something I am missing?

Upvotes: 2

Views: 430

Answers (3)

Thilo Schulz
Thilo Schulz

Reputation: 105

There are several possibilities where your program is crashing, but most likely it is because you're missing some important checks and the file "test.txt" is missing in the working directory of your program.

First check that is missing is whether testfile is NULL:

testfile = fopen("test.txt", "r");

The testfile FILE pointer is passed unchecked to getline() which may crash the program if it is passed an invalid file pointer. As Barmar remarked previously, even if testfile is valid, getline() itself may also fail, however on my current Debian the manpage doesn't say what happens to the line pointer on error condition, so I would just check for return value < 0 to detect an error and, in your case, not use or free the pointer at all afterwards.

As a last remark, you should learn how to use gdb if you're learning this kind of stuff. Use like so:

$ gcc -ggdb3 -o pipetest pipetest.c
$ gdb pipetest 
GNU gdb (Debian 7.7.1+dfsg-5) 7.7.1
[...]
(gdb) run
Starting program: /home/thilo/code/test/pipetest 

Program received signal SIGSEGV, Segmentation fault.
_IO_getdelim (lineptr=0x7fffffffe068, n=0x7fffffffe060, delimiter=10, fp=0x0) at iogetdelim.c:56
56      iogetdelim.c: No such file or directory.
(gdb) bt
#0  _IO_getdelim (lineptr=0x7fffffffe068, n=0x7fffffffe060, delimiter=10, fp=0x0) at iogetdelim.c:56
#1  0x00000000004008fb in write_to_pipe (file=4) at pipetest.c:28
#2  0x00000000004009d9 in main () at pipetest.c:62
(gdb) frame 1
#1  0x00000000004008fb in write_to_pipe (file=4) at pipetest.c:28
28        getline(&line, &len, testfile);
(gdb) print line
$1 = 0x0

Upvotes: 1

Petr Skocik
Petr Skocik

Reputation: 60068

It will likely work fine once you create the test.txt file. That fixed it on my machine, at least.

In C, you usually need to do some quite tedious error checking to write programs robustly. E.g., you should have written something like:

int read_from_pipe (int file) {
  FILE *stream;
  int c;
  if((stream = fdopen (file, "r"))==NULL) goto err;

  while ((c = fgetc (stream)) != EOF){
    putchar (c);
  }
  if(ferror(stream)){ int er=errno; fclose (stream); errno=er; goto err; }
  return 0;
err:
  perror("read"); return -errno; 
}

etc.

Had your fopen line for the test file looked like:

if(!(testfile = fopen("test.txt", "r"))) { perror("write"); return -errno; }

you might have gotten a nice "write: No such file or directory" message.

Upvotes: 1

Chris TM
Chris TM

Reputation: 1

This code is running properly on my machine (Linux 3.2.0-4-amd64 #1 SMP Debian 3.2.68-1+deb7u2 x86_64 GNU/Linux) as is without modifications. I removed the 'test.txt' file and got a segmentation fault as a result.

Therefore I think the problem you are having is either the 'test.txt' file does not exist or you do not have read permissions for the user that you are running the program under.

Upvotes: 0

Related Questions