terminal
I'm trying to debug a code in linux using gdb, first time using it. Can someone point out what's wrong in my processes or is this a normal occurance due to the code?
The code is
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char *argv[]) {
char buffer[100];
long int n1;
int fd1, fd2;
if (((fd1 = open(argv[1], O_RDONLY)) == -1) ||
((fd2 = open(argv[2], O_CREAT|O_WRONLY|O_TRUNC,0700)) == -1)) {
perror("file problem ");
exit(1);
}
while ((n1 = read(fd1, buffer, 512) > 0))
if (write(fd2, buffer, n1) != n1) {
perror("writing problem ");
exit(3);
}
// in Case of an error exit from the loop
if (n1 == -1) {
perror("Reading problem ");
exit(2);
}
close(fd1);
close(fd2);
exit(0);
}
Hi there i am trying to make such a program in which the the two fds stdin and fifo monitor by select() and communicate with each other.
select() will monitor either fifo ready for reading or stdin.
server.c
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <string.h>
#include <sys/select.h>
int main(int argc,char *argv[]){
int f,fifo_read,fifo_write,status;
fd_set readset;
FD_ZERO(&readset);
char str[512]="start";
if(argc !=2)
if(argc != 2){
printf("\nError: %s required argument [Fifo Name]\n\n",argv[0]);
exit(EXIT_FAILURE);
}
if ((open(argv[1], O_RDWR)) < 0){
f = mkfifo(argv[1],S_IRWXU);
if(f<0){
perror("Error While Creating FIFO ");
exit(EXIT_FAILURE);
}
else
printf("FIFO Created Successfully...\n");
}
while(strcmp(str,"end")!=0){
fifo_write= open(argv[1],O_WRONLY);
FD_SET(fifo_read, &readset);
FD_SET(STDIN_FILENO, &readset);
status = select(fifo_read+1, &readset, NULL, NULL, NULL);
if(status==-1){
perror("Error While Calling select() system call ");
//exit(EXIT_FAILURE);
}
if(FD_ISSET(STDIN_FILENO,&readset)){
if(fifo_write<0)
perror("\nError while writing on pipe ");
else{
printf("\nServer>> ");
scanf("%s",str);
write(fifo_write,str,strlen(str));
close(fifo_write);
}
}
fifo_read=open(argv[1],O_RDONLY);
if(FD_ISSET(fifo_read,&readset)){
if(fifo_read<0)
perror("\nError while reading from pipe ");
else{
read(fifo_read,str,strlen(str));
close(fifo_read);
printf("\nJiya%s",str);
}
}
}
return 0;
}
client.c
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <string.h>
#include <sys/select.h>
int main(int argc,char *argv[]){
int f,fifo_read,fifo_write,status;
fd_set readset;
FD_ZERO(&readset);
char str[512]="start";
while(strcmp(str,"end")!=0){
fifo_write= open(argv[1],O_WRONLY);
FD_SET(fifo_read, &readset);
FD_SET(STDIN_FILENO, &readset);
status = select(fifo_read+1, &readset, NULL, NULL, NULL);
if(status==-1){
perror("Error While Calling select() system call ");
//exit(EXIT_FAILURE);
}
if(FD_ISSET(fifo_read,&readset)){
if(fifo_read<0)
printf("\nError opening read pipe");
else{
read(fifo_read,str,strlen(str));
close(fifo_read);
printf("\n%s",str);
}
}
fifo_read=open(argv[1],O_RDONLY);
if(FD_ISSET(STDIN_FILENO,&readset)){
if(fifo_write<0)
printf("\nError opening write pipe");
else{
printf("\nClient>> ");
scanf("%s",str);
write(fifo_write,str,strlen(str));
close(fifo_write);
}
}
}
return 0;
}
I have posted a working, somewhat simplified version of your code below. This code reads from STDIN in the client and sends that input through the pipe created by mkfifo to the server. The server loops reading from its end of the pipe and echoes what it read to STDOUT.
Client output:
CLIENT > Message1
CLIENT > Message2
CLIENT > Yet another message.
CLIENT > A fourth message, but this one is quite a bit longer than the first messages.
CLIENT > end
Server output:
SERVER: Got 8 byte message: 'Message1'
SERVER: Got 8 byte message: 'Message2'
SERVER: Got 20 byte message: 'Yet another message.'
SERVER: Got 77 byte message: 'A fourth message, but this one is quite a bit longer than the first messages.'
EOF encountered...
I'll highlight some of the main differences:
I first create the pipe special file via mkfifo in the server. I then open the special file in the server and the client. This happens before the loop, and the file descriptors stay open during the loop instead of being repeatedly opened and closed.
The client only writes to the pipe and the server only reads from the pipe. At least on Linux, pipes are unidirectional (pipe man page: Pipes and FIFOs (also known as named pipes) provide a unidirectional interprocess communication channel. A pipe has a read end and a write end...) Two pipes may be used for bidirectional communication on Linux, and even on systems that support bidirectional pipes, using two pipes would still be supported and would be more portable.
When calling read, you should use the total size of the str buffer, not strlen(str). Also, str should be cleared between reads, so as to not contain old data (memset in new code).
I used fgets instead of scanf.
After the server opens the FIFO, I unlink the file, so that it is automatically deleted from the file system. The underlying file object will still exist until processes using it have terminated. This is optional.
Server:
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/select.h>
#include <sys/stat.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
int fifo_read = -1;
char str[512]= "";
fd_set readset;
FD_ZERO(&readset);
if (argc != 2) {
printf("Usage: %s FIFO_NAME\n", argv[0]);
exit(EXIT_FAILURE);
}
/* Server will make the FIFO, both sides will open it */
if (mkfifo(argv[1], S_IRWXU) == -1) {
perror("mkfifo()");
exit(EXIT_FAILURE);
}
if ((fifo_read = open(argv[1], O_RDONLY)) == -1) {
perror("open()");
exit(EXIT_FAILURE);
}
if (unlink(argv[1]) == -1) {
perror("unlink()");
exit(EXIT_FAILURE);
}
while (1) {
FD_SET(fifo_read, &readset);
if (select(fifo_read + 1, &readset, NULL, NULL, NULL) == -1) {
perror("select()");
exit(EXIT_FAILURE);
}
if (FD_ISSET(fifo_read, &readset)) {
ssize_t bytes_read;
memset(str, 0, sizeof(str));
bytes_read = read(fifo_read, str, sizeof(str));
if (bytes_read == -1) {
perror("read()");
exit(EXIT_FAILURE);
}
else if (bytes_read == 0) {
printf("EOF encountered...\n");
break;
}
printf("SERVER: Got %ld byte message: '%s'\n", bytes_read, str);
}
}
if (close(fifo_read) == -1) {
perror("close()");
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}
Client:
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/select.h>
#include <sys/stat.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
int fifo_write = -1;
char str[512] = "";
fd_set readset;
FD_ZERO(&readset);
if (argc != 2) {
printf("Usage: %s FIFO_NAME\n", argv[0]);
exit(EXIT_FAILURE);
}
if ((fifo_write = open(argv[1], O_WRONLY)) == -1) {
perror("open()");
exit(EXIT_FAILURE);
}
while (1) {
printf("CLIENT > ");
fflush(stdout);
FD_SET(STDIN_FILENO, &readset);
if (select(STDIN_FILENO + 1, &readset, NULL, NULL, NULL) == -1) {
perror("select()");
exit(EXIT_FAILURE);
}
if (FD_ISSET(STDIN_FILENO, &readset)) {
memset(str, 0, sizeof(str));
if (!fgets(str, sizeof(str), stdin)) {
printf("fgets() failed to read a line.\n");
exit(EXIT_FAILURE);
}
// See https://stackoverflow.com/questions/2693776/removing-trailing-newline-character-from-fgets-input
str[strcspn(str, "\r\n")] = 0;
if (strcmp(str, "end") == 0) {
break;
}
if (write(fifo_write, str, strlen(str)) == -1) {
perror("write()");
exit(EXIT_FAILURE);
}
}
}
if (close(fifo_write) == -1) {
perror("close()");
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}
Here i Got the Solution :)
server.c
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/select.h>
#include <string.h>
#include <sys/stat.h>
#include <errno.h>
int main(int argc, char *argv[])
{
if(argc != 2){
printf("\nError: %s required argument [Fifo Name]\n\n",argv[0]);
exit(EXIT_FAILURE);
}
int fd,wr,rd,ret;
fd_set readset;
if(mkfifo(argv[1],S_IRWXU)==-1){
if(errno!=EEXIST)
perror("Error unable to create FIFO ");
else
perror("Error unable to create FIFO ");
exit(EXIT_FAILURE);
}
else
printf("FIFO created Successfully!\n\n");
fd = open(argv[1],O_RDWR);
if(fd==-1){
perror("Error Failed to open fifo\n");
exit(EXIT_FAILURE);
}
while(!0){
FD_ZERO(&readset);
FD_SET(fd,&readset);
FD_SET(STDIN_FILENO,&readset);
sleep(1);
ret = select(fd+1,&readset,NULL,NULL,NULL);
if(ret==-1){
perror("Error select() ");
exit(EXIT_FAILURE);
}
char str[512]="";
if(FD_ISSET(STDIN_FILENO,&readset)){
//fprintf(stderr, ">> ");
rd = read(STDIN_FILENO,str,sizeof(str));
if(rd==-1){
perror("Error while reading from fifo");
exit(EXIT_FAILURE);
}
char temp[512]="Server :: ";
strcat(temp,str);
wr = write(fd,temp,sizeof(temp));
if(wr==-1){
perror("Error while writing to fifo ");
exit(EXIT_FAILURE);
}
continue;
}
if(FD_ISSET(fd,&readset)){
rd = read(fd,str,sizeof(str));
if(rd==-1){
perror("Error while reading from fifo");
exit(EXIT_FAILURE);
}else if(rd==0)
continue;
//fprintf(stderr,"P2: %s\n",str);
printf("%s\n",str);
//write(STDOUT_FILENO,str,sizeof(str));
}
}
}
client.c
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/select.h>
#include <string.h>
#include <sys/stat.h>
#include <errno.h>
int main(int argc, char *argv[])
{
if(argc != 2){
printf("\nError: %s required argument [Fifo Name]\n\n",argv[0]);
exit(EXIT_FAILURE);
}
int fd,wr,rd,ret;
fd_set readset;
fd = open(argv[1],O_RDWR);
if(fd==-1){
perror("Error Failed to open fifo\n");
exit(EXIT_FAILURE);
}
while(!0){
FD_ZERO(&readset);
FD_SET(fd,&readset);
FD_SET(STDIN_FILENO,&readset);
sleep(2);
ret = select(fd+1,&readset,NULL,NULL,NULL);
if(ret==-1){
perror("Error select() ");
exit(EXIT_FAILURE);
}
char str[512]="";
if(FD_ISSET(fd,&readset)){
rd = read(fd,str,sizeof(str));
if(rd==-1){
perror("Error while reading from fifo");
exit(EXIT_FAILURE);
}else if(rd==0)
continue;
//fprintf(stderr,"P2: %s\n",str);
printf("%s\n",str);
//write(STDOUT_FILENO,str,sizeof(str));
}
if(FD_ISSET(STDIN_FILENO,&readset)){
//fprintf(stderr, ">> ");
rd = read(STDIN_FILENO,str,sizeof(str));
if(rd==-1){
perror("Error while reading from fifo");
exit(EXIT_FAILURE);
}
char temp[512]="Client :: ";
strcat(temp,str);
wr = write(fd,temp,sizeof(temp));
if(wr==-1){
perror("Error while writing to fifo ");
exit(EXIT_FAILURE);
}
continue;
}
}
}
and the output is :
I'm beginning with pipes under Linux and I have a problem with my code.
I wanted to test sending an integer through the fifo so I code a small program to test it.
First I open the read only descriptor and then the write only one as precised in the documentation.
I send the number to the pipe and close the write descriptor.
However, when I'm trying to read from the pipe, it says that I have a bad file descriptor, I don't understand why it's not working because as the descriptor is the good one and is oppened with good option (O_RDONLY | O_NONBLOCK).
Here is my code :
void main(void)
{
int modePipeWrite, modePipeRead;
if(mkfifo("test.fifo", 0777) == -1)
{
perror("mkfifo");
exit(EXIT_FAILURE);
}
if(modePipeRead = open("test.fifo", O_RDONLY | O_NONBLOCK) == -1)
{
perror("openRead");
exit(EXIT_FAILURE);
}
if(modePipeWrite = open("test.fifo", O_WRONLY | O_NONBLOCK) == -1)
{
perror("openWrite");
exit(EXIT_FAILURE);
}
int n = 0;
if(write(modePipeWrite, &n, sizeof(n)) == -1)
{
perror("write");
}
printf("Send value: %d\n", n);
close(modePipeWrite);
int mode;
while(1)
{
if(read(modePipeRead, &mode, sizeof(mode)) == -1)
{
perror("read");
}
printf("Received value: %d\n", getpid(), mode);
sleep(1);
}
}
And the output :
./a.out
Send value: 0
read: Bad file descriptor
Received value: -1877110288
read: Bad file descriptor
Received value: -1877110288
read: Bad file descriptor
Received value: -1877110288
I don't understand what could be wrong here. If someone have some advices I would be glad to hear it.
Your code has a couple of issues, which you would've found if you compiled it with all warnings enabled. If you use gcc, the following options are nice/mandatory:
-Wall -Wextra -Werror -pedantic
One issue is that you don't assign the return value of open() to the file descriptors. You need to add braces around the assignment, or move it out of the if-statements.
Here's a working example, using a thread to read:
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <pthread.h>
static void *reader(void *arg)
{
int fd, val;
if ((fd = open("test.fifo", O_RDONLY)) == -1) {
perror("openRead");
exit(EXIT_FAILURE);
}
if (read(fd, &val, sizeof val) == -1)
perror("read");
else
printf("Received value: %d\n", val);
close(fd);
return NULL;
}
int main(void)
{
int modePipeWrite, modePipeRead;
pthread_t readerid;
if (mkfifo("test.fifo", 0777) == -1) {
perror("mkfifo");
exit(EXIT_FAILURE);
}
pthread_create(&readerid, NULL, reader, NULL);
sleep(1);
if ((modePipeWrite = open("test.fifo", O_WRONLY)) == -1) {
perror("openWrite");
exit(EXIT_FAILURE);
}
int n = 1234;
if (write(modePipeWrite, &n, sizeof n) == -1)
perror("write");
else
printf("Sent value: %d\n", n);
sleep(1);
close(modePipeWrite);
return 0;
}
I'm writing a simple application which will use anonymous pipes to communicate with child process called using execl().
Child process is simple echo application.
I want to redirect stdin and stdout to pipes and use them to receive data sent by child in parent.
Now only two lines are echoed.
Any ideas what is wrong?
Here is my code:
(parent.c)
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <errno.h>
int main()
{
int parent_to_child[2];
int child_to_parent[2];
if(pipe(parent_to_child) == -1) exit(-1);
if(pipe(child_to_parent) == -1) exit(-1);
switch(fork())
{
case -1: exit(-1);
case 0: //child
if(close(0) == -1) exit(-1);
if(dup(parent_to_child[0]) != 0) exit(-1);
fprintf(stderr, "stdin changed\n");
if(close(1) == -1) exit(-1);
if(dup(child_to_parent[1]) != 1) exit(-1);
fprintf(stderr, "stdout changed\n");
close(parent_to_child[0]);
close(parent_to_child[1]);
close(child_to_parent[0]);
close(child_to_parent[1]);
execl("./child_process","child_process", (char*)NULL);
exit(-1);
default: //parent
close(parent_to_child[0]);
close(child_to_parent[1]);
size_t size = 1024;
char* line = (char *) malloc(size);
while(getline(&line, &size, stdin) != -1)
{
if(write(parent_to_child[1], line, (strlen(line)+1)*sizeof(char)) == -1)
{
printf("%d", errno);
exit(-1);
}
read(child_to_parent[0], line, size);
printf("%s", line);
}
}
return 0;
}
(child_process.c)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
size_t size = 1024;
char* line = (char*) malloc(size);
setlinebuf(stdout);
setlinebuf(stdin);
fprintf(stderr, "child started\n");
while(getline(&line, &size, stdin) != -1)
{
printf("%s", line);
}
fprintf(stderr, "exiting");
free(line);
return 0;
}
I'm writing a coprocess program using pipe. It works fine when the child read some data, handle it and output it. But when I read all the data and handle it, it just pending. Any body have some idea? Thank you.
Here is the source code:
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
int main()
{
#define MAXSIZE 1024
char workload[MAXSIZE];
char result[MAXSIZE];
workload[strlen(workload)] = EOF;
int workload_size = strlen(workload);
int fd1[2], fd2[2];
int n;
pid_t pid;
if (pipe(fd1) < 0 || pipe(fd2) < 0) {
fprintf(stderr, "pipe error: %s\n", strerror(errno));
exit(1);
}
if ((pid = fork()) < 0) {
fprintf(stderr, "fork error: %s\n", strerror(errno));
exit(1);
} else if (pid > 0) {
close(fd1[0]);
close(fd2[1]);
while(fgets(workload, MAXSIZE, stdin) != NULL)
{
workload_size = strlen(workload);
if (write(fd1[1], workload, workload_size) != workload_size) {
fprintf(stderr, "write to pipe error: %s\n", strerror(errno));
exit(1);
}
if ((n = read(fd2[0], result, MAXSIZE)) < 0) {
fprintf(stderr, "read from pipe error: %s\n", strerror(errno));
exit(1);
}
if (n == 0) {
fprintf(stderr, "child closed the pipe\n");
exit(1);
}
result[n] = 0;
if (puts(result) == EOF) {
fprintf(stderr, "fputs error\n");
exit(1);
}
}
} else {
close(fd1[1]);
close(fd2[0]);
if (fd1[0] != STDIN_FILENO) {
if (dup2(fd1[0] ,STDIN_FILENO) != STDIN_FILENO) {
fprintf(stderr, "dup2 error to stdin.\n");
exit(1);
}
close(fd1[0]);
}
if (fd2[1] != STDOUT_FILENO) {
if (dup2(fd2[1] ,STDOUT_FILENO) != STDOUT_FILENO) {
fprintf(stderr, "dup2 error to stdout.\n");
exit(1);
}
close(fd2[1]);
}
if (execl("./a.out", "a.out", NULL) < 0) {
fprintf(stderr, "execl error: %s\n", strerror(errno));
exit(1);
}
exit(0);
}
return 0;
}
Here is the source code of a.out, it works well with this:
#include <stdio.h>
#include <string.h>
int main()
{
#define MAXSIZE 1024
char x[MAXSIZE];
int n;
while(scanf("%s", x) != EOF)
{
printf("len:%d %s", strlen(x), x);
fflush(stdout);
}
return 0;
}
But it seems just pending when I write the code like this:
#include <stdio.h>
#include <string.h>
int main()
{
#define MAXSIZE 1024
char x[MAXSIZE];
int n;
while(scanf("%s", x) != EOF);
printf("Ok\n");
fflush(stdout);
return 0;
}
The way you are calling scanf with %s may overflow the x buffer. You should at least modify the scanf with a width modifier.
#include <stdio.h>
#include <string.h>
int main()
{
#define MAXSIZE 1024
char x[MAXSIZE];
int n;
while(scanf("%1024s", x) != EOF)
{
printf("len:%d %s", strlen(x), x);
fflush(stdout);
}
return 0;
}
And similarly for your other program.
The reason your program is getting blocked is because your second a.out program is looped doing another scanf, when at the same time the parent program is trying to read a response back into result.
You should test and loop while not feof and you might use popen & pclose
You probably want to use some multiplexing system call like poll