LinuxQuestions.org
Welcome to the most active Linux Forum on the web.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 12-06-2012, 03:30 PM   #1
alphisb0t
Member
 
Registered: Jun 2004
Distribution: gentoo 2008.desktop
Posts: 110

Rep: Reputation: 15
pipes and X applications


Hello.

I'm writing a small C program that forks(), dups(), and execve()s an X application that reads its input from its stdin (as opposed to params).

I can spawn it and its definitely running, however the parent process waits for input and never gets it as the X application is waiting for me to select an option. The problem is....the visual X interface never appears! Its just hidden!

I wrote directly to the X applications's STDOUT file description via /proc and then terminated the process which yielded the correct response in my waiting parent process. So it should be working but the X application just stays invisible for some reason.

Is there any way to make this window show?

Thanks for any help!
 
Old 12-09-2012, 09:52 AM   #2
theNbomr
LQ 5k Club
 
Registered: Aug 2005
Distribution: OpenSuse, Fedora, Redhat, Debian
Posts: 5,399
Blog Entries: 2

Rep: Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908
Your description of the problem is confusing. Some code (in [CODE] [/CODE] tags, of course) that demonstrates the problem would be most useful here.

--- rod.
 
Old 02-09-2013, 01:55 PM   #3
alphisb0t
Member
 
Registered: Jun 2004
Distribution: gentoo 2008.desktop
Posts: 110

Original Poster
Rep: Reputation: 15
I'm trying to write to stdin in a program called dmenu. i can't seem to get it to work at all. here is the code.

Code:
pid_t pid;
        char *exe_buffer[64] = { "/usr/bin/dmenu" };
        char rbuffer[1024];
        int wres;

        pid=fork();

        if(pid==-1) { printf("error forking\n"); return; }

        if(pid==0)
        {
                //debug
                printf("execve: %s %s %s\n",exe_buffer[0],exe_buffer[1],exe_buffer[2]);

                //child
                dup2(pwrite[0],0);
                dup2(pread[1],1);
                dup2(pread[1],2);

                //execve
                execve(exe_buffer[0],exe_buffer,environ);
                printf("..uh..\n");
        }
        else
        {
                sleep(2);
                printf("writing to child..\n");
                //write(pwrite[1],menu,strlen(menu));
                wres=write(pwrite[1],"item1\nitem2\n",12);
                printf("write result: %i\n",wres);
                fsync(pwrite[1]);
                printf("waiting for child..\n");
                wait();
                printf("reading from child..\n");
                read(pread[0],rbuffer,1024);
                printf("read from child: %s\n",rbuffer);
        }
I don't see why reading/writing to an external program via pipes is so....complicated. If anyone can tell me what I'm doing wrong it would be very helpful. I've read the man pages of the functions I'm using and still don't see what the problem is.
 
Old 02-09-2013, 03:36 PM   #4
ntubski
Senior Member
 
Registered: Nov 2005
Distribution: Debian, Arch
Posts: 3,780

Rep: Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081
Quote:
Originally Posted by alphisb0t View Post
I'm trying to write to stdin in a program called dmenu.
dmenu waits for an EOF on stdin before displaying anything. In terms of your C program, you have to close(pwrite[1]), before read(pread[0]).
 
Old 02-09-2013, 10:40 PM   #5
alphisb0t
Member
 
Registered: Jun 2004
Distribution: gentoo 2008.desktop
Posts: 110

Original Poster
Rep: Reputation: 15
Ah indeed EOF IS needed (and man page even mentions this too). I added and it didn't fix the problem. For *SOME* reason I had to close the parent only FDs in the child and magically it works!

Here is the code (from child process)
Code:
if(pid==0)
        {
                //debug
                printf("execve: %s %s %s\n",exe_buffer[0],exe_buffer[1],exe_buffer[2]);

                //child
                dres=dup2(pwrite[0],STDIN_FILENO);
                if(dres==-1) { printf("error duping handle!\n"); return; }
                dres=dup2(pread[1],STDOUT_FILENO);
                if(dres==-1) { printf("error duping handle!\n"); return; }
                dres=dup2(pread[1],STDERR_FILENO);
                if(dres==-1) { printf("error duping handle!\n"); return; }

                //close parent only used fds
                close(pread[0]);
                close(pwrite[1]);

                //execve
                execve(exe_buffer[0],exe_buffer,environ);
                printf("..uh..\n");
        }
Notice the new lines close() for the pread[0] and pwrite[1]. Adding this makes it work! Commenting them out again makes it not work! I don't understand why this is necessary seeing as how the child (dmenu) only reads from stdin and writes to stdout. I get the EOF thing in the parent (not shown) but don't get why this additional change it needed.
 
Old 02-10-2013, 08:46 AM   #6
ntubski
Senior Member
 
Registered: Nov 2005
Distribution: Debian, Arch
Posts: 3,780

Rep: Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081
Ah, the explanation is in pipe(7):

Quote:
If all file descriptors referring to the write end of a pipe have been closed, then an attempt to read(2) from the pipe will see end-of-file (read(2) will return 0). ... An application that uses pipe(2) and fork(2) should use suitable close(2) calls to close unnecessary duplicate file descriptors; this ensures that end-of-file and SIGPIPE/EPIPE are delivered when appropriate.
So you need close(pwrite[1]) in the child else close(pwrite[1]) in the parent has no effect.
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Pipes jayant17 Linux - Newbie 3 02-27-2010 03:04 PM
LXer: Names Pipes... or how to get two separate applications to interact LXer Syndicated Linux News 0 06-29-2009 05:00 AM
Mozilla Firefox 3.0.4; few applications in 'applications' tab of 'preferences'; SW12. mitchellray Linux - Newbie 1 03-27-2009 08:56 PM
pipes leedude Programming 4 05-20-2008 06:52 PM
how to use pipes? rabbit2345 Linux - Software 2 03-29-2008 01:52 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 12:51 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration