khernik
khernik

Reputation: 2091

Strange output using pipes for thread communication

I have three threads - the first one reads a string, the second counts characters, and the third displays it. I'm using pipes for communication.

However, after running it nothing happens, and when I type in something, let's say "asd", I get:

asd
asd
Enter the message: Enter the message:

or

asd
asd
Enter the message:

What's wrong?

#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>
#include <linux/stat.h>
#include <pthread.h>
#include <string.h>

int first[2];
int second[2];

void *input(void *ptr)
{
   char str[100];
   int length;

   while(1)
   {
      printf("Enter the message: ");
      length = read(STDIN_FILENO, str, sizeof(str));

      if(length <= 0)
      {
         if(length == -1)
            perror("read");
         close(first[1]);
         exit(2);
      }
      if(write(first[1], str, length) != length)
      {
         perror("write");
         exit(2);
      }
   }
}

void *countChars(void *ptr)
{
   char str[100];
   int length, count = 0;

   while(1)
   {
      length = read(first[0], str, sizeof(str));
      if(length <= 0)
      {
         if(length == -1)
            perror("read");
         close(first[0]);
         close(second[1]);
         exit(2);
      }
      if(write(STDOUT_FILENO, str, length) != length)
      {
         perror("write");
         exit(2);
      }

      while(str[count] != '\n') count++;

      write(second[1], &count, sizeof(count));

      count = 0;
   }
}

void *output(void *ptr)
{
   int length, count = 0;

   while(1)
   {
      length = read(second[0], &count, sizeof(count));
      if(length <= sizeof(count))
      {
         close(second[0]);
         exit(2);
      }

      printf("Number of characters: %d\n", count);
   }
}

int main()
{
   pthread_t t1, t2, t3;

   if(pipe(first) == -1)
   {
      printf("First pipe error");
      exit(1);
   }

   if(pipe(second) == -1)
   {
      printf("Second pipe error");
      exit(1);
   }

   pthread_create(&t1, NULL, input, NULL);
   pthread_create(&t2, NULL, countChars, NULL);
   pthread_create(&t3, NULL, output, NULL);

   pthread_join(t1, NULL);
   pthread_join(t2, NULL);
   pthread_join(t3, NULL);

   return 0;
}

Upvotes: 0

Views: 86

Answers (2)

David C. Rankin
David C. Rankin

Reputation: 84642

You have a logic problem in your code. In output:

if (length < sizeof (count)) {    // not <=

length will always equal sizeof (count) on successful write of an integer.

Also, wrapping everything function in while (1) {...} is not the safest. Remove the while (1) loops and replace them with a return at the end of the function. i.e. return ptr; For example:

void *
output (void *ptr) {
    int length, count = 0;

        printf ("\noutput:\n\n");

//     while (1) {
        length = read (second[0], &count, sizeof (count));
        printf ("count: %d\n", count);

        if (length < sizeof (count)) {    // not <=
            printf ("closing second[0] and exiting\n");
            close (second[0]);
            exit (2);
        }

        printf ("Number of characters: %d\n", count);
//     }
    return ptr;
}

Upvotes: 1

Christopher C. S. Ke
Christopher C. S. Ke

Reputation: 265

That's because printf only writes content to buffer. The content will be actually sent to stdout once it receives a line feed ('\n') or fflush(stdout) is called.

You can try to add flush(stdout); next to the printf("Enter the message: ");, and you should see what you expect.

Upvotes: 1

Related Questions