Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

[ace-users] IPC: Questions about using ACE_Pipes and ACE_Process

58 views
Skip to first unread message

Manoj Srivastava

unread,
Apr 5, 2001, 5:11:57 PM4/5/01
to
Hi,

TAO VERSION: 1.1.14
ACE VERSION: 5.1.14

HOST MACHINE and OPERATING SYSTEM: WINDOWS NT 4.0
TARGET MACHINE and OPERATING SYSTEM, if different from HOST:
COMPILER NAME AND VERSION (AND PATCHLEVEL): VC++ 6.0

AREA/CLASS/EXAMPLE AFFECTED: Unable to read the data from the Child in
the Parent
[What example failed? What module failed to compile?]
I have written an example that uses the ACE_process, ACE_Process_Options and
ACE_Pipe . The source code has been pasted in this mail.

DOES THE PROBLEM AFFECT:
COMPILATION? NO
If so, what do your $ACE_ROOT/ace/config.h and
$ACE_ROOT/include/makeinclude/platform_macros.GNU contain?
LINKING? NO

On Unix systems, did you run make realclean first?
EXECUTION? YES
OTHER (please specify)?
[Please indicate whether ACE/TAO, your application, or both are affected.]

My example Program has been affected because of using the ACE_Process.
My example program is unable to read the data from the child process in the
Parent process. The output of this below Program has been attached to this
mail.

SYNOPSIS:
[Brief description of the problem]

I have been trying to create a simple two way connection to a
child process using a combination of ACE_Process and ACE_Pipes. Under
standard UNIX, this is easily done using a variation of from
Richard Stevens coprocesses example; in the listing 1 below (this is
a working snippet).

However, when I tried to move to a portable solution, running
on an NT box, using ACE_Process and a pair of ACE_Pipes, the read in
the parent fails, even though the child process does seem to be
pumping data into the write end of the pipe. In Listing 2 below, the
printf line that is supposed to print data from ``Child ------>blah''
is never executed.

On a UNIX box, a blocking read does not return 0 until all
writers for that pipe close their ends of the pipe; and thus the
simple read in a while loop method works. I had expected the same
semantics from a read on the NT box; unfortunately, that does not
seem to be what is happening.

At this point, I am stumped. Is there something simple that I
am missing?

Thanks,

manoj

Listing 1, working example from a UNIX box, for comparison
----------------------------------------------------------------------
int ret = pipe(ctrlpipe);
if(ret < 0)
{
perror("Error opening control pipe\n");
ACE_THROW_RETURN (CORBA::BAD_PARAM (), 0);
} /* end of if() */

int ret = pipe(datapipe);
if(ret < 0)
{
perror("Error opening data pipe\n");
ACE_THROW_RETURN (CORBA::BAD_PARAM (), 0);
} /* end of if() */

if((childpid = fork()) == 0)
{
close(ctrlpipe[1]);
close(datapipe[0]);
ret = execle ("/home/quite/Pipes/Remos_Graph_Probe",
"Remos_Graph_Probe",
(char **) node_names,
num_nodes,
(char *) 0,
env_init);
perror("Error executing Remos_Graph_Probe\n");
} /* end of if((childpid = fork()) == ) */
else
{
string message;
size_t len;
char buff[MAXLINE];

close(ctrlpipe[0]);
close(datapipe[1]);

while(read(datapipe[0],buff,MAXLINE))
{
message.append(buff);
} /* end of while(read(,buff,MAXLINE)>0) */
} /* end of else */
----------------------------------------------------------------------

Listing 2, on NT. No data is ever read from the PIPE.
----------------------------------------------------------------------
#include <stdio.h>
#include "ace/OS.h"
#include "ace/Log_Msg.h"
#include "ace/Pipe.h"
#include "ace/Process.h"

static const char * executable = "test.exe";

int
main (int argc, char *argv[])
{
ssize_t n;
char buff[BUFSIZ];

ACE_Process new_process;
ACE_Pipe data_pipe; // Pipe from parent to child, for control
ACE_Pipe control_pipe; // Pipe from child to parent, data returned
pid_t childpid, testpid;
ACE_Process_Options options;

/// Open the data pipe, or exit
if (data_pipe.open () == -1)
ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "data_pipe.open"), -1);
/// Open the control pipe
if (control_pipe.open () == -1)
ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "control_pipe.open"), -1);

options.set_handles (control_pipe.read_handle(), data_pipe.write_handle());
options.command_line(executable);

if ( (childpid = new_process.spawn (options) ) == -1)
{
int error = ACE_OS::last_error ();
ACE_ERROR_RETURN ((LM_ERROR, "%p errno = %d.\n",
"test_more", error), -1);
}
else
{
ACE_DEBUG ((LM_DEBUG, "Process created \n"));
ACE_OS::printf ("The child pid is ->%d\n", childpid);
while( (n = ACE_OS::read(data_pipe.read_handle (), buff, BUFSIZ) ) > 0)
{
buff[n] = 0;
ACE_OS::printf ("data from Child ------>\n%s\n", buff);
}

ACE_DEBUG ((LM_DEBUG, "Done with while loop \n"));
data_pipe.close();
control_pipe.close();
ACE_exitcode status;

//new_process.wait (&status);
while ((testpid = new_process.wait (&status)) != childpid)
printf("\n %d ->%d",childpid,testpid);

printf("\n %d ->%d",childpid,testpid);
ACE_DEBUG ((LM_DEBUG, "\nProcess exit with status %d\n", status));
}
return 0;
}

SAMPLE FIX/WORKAROUND:
[If available ]


--
Those who meditate with perseverance, constantly working hard at it,
are the wise who experience Nirvana, the ultimate freedom from
chains. 23
Manoj Srivastava <sriv...@debian.org> <http://www.debian.org/%7Esrivasta/>
1024R/C7261095 print CB D9 F4 12 68 07 E4 05 CC 2D 27 12 1D F5 E8 6E
1024D/BF24424C print 4966 F272 D093 B493 410B 924B 21BA DABB BF24 424C

Douglas C. Schmidt

unread,
Apr 5, 2001, 7:51:41 PM4/5/01
to
Hi Manoj,

Thanks for using the PRF!

I think what's going on here is that the NT process semantics simply
don't match up 1-to-1 with the UNIX semantics. While it's certainly
possible to write portable programs that use ACE to communicate via
IPC mechanisms (e.g., sockets) on both platforms, you shouldn't expect
stuff like the process model to work the same work since the semantics
are so different.

ACE does the best it can to encapsulate these differences, but as my
great uncle Duane the farmer used to say "you can't make chicken feed
outta chicken droppings"!

Take care,

Doug


--
Dr. Douglas C. Schmidt, Associate Professor TEL: (949) 824-1901
Dept of Electrical & Computer Engineering FAX: (949) 824-2321
616E Engineering Tower WEB: www.ece.uci.edu/~schmidt/
University of California, Irvine, 92697-2625 NET: sch...@uci.edu

Manoj Srivastava

unread,
Apr 5, 2001, 11:53:39 PM4/5/01
to
>>"Douglas" == Douglas C Schmidt <sch...@cs.wustl.edu> writes:

Douglas> I think what's going on here is that the NT process
Douglas> semantics simply don't match up 1-to-1 with the UNIX
Douglas> semantics. While it's certainly possible to write portable
Douglas> programs that use ACE to communicate via IPC mechanisms
Douglas> (e.g., sockets) on both platforms, you shouldn't expect
Douglas> stuff like the process model to work the same work since the
Douglas> semantics are so different.

Understood. Given that, permit me to turn my question around:
What is the canonical way to detect the end-of-file marker using
ACE_Pipe on NT? Or perhaps I should ask for the pattern for using
ACE_Process and ACE_Pipe on NT, and being able to read data
transmitted by the child process through the pipe, ensuring that we
get all the data written by the child, given that the child may take
significant time to generate this data? (that is my underlying
problem)

I've trawled through the examples in $ACE_ROOT/examples/, and
the closest example I found was in OS/Process/imore.cpp (which may
well have been the original template of the code I am working with),
but even that does not provide an example of reading from the pipe on
win32. Come to think of it, the parent does not even write to the
pipe in win32 section (the print_file function is only invoked on non
win32 code).

I tried reading through ace/Pipe.cpp, but got lost in the
ACE_SOCK_Acceptor/Connector bits in the win32 code.

manoj
--
Men aren't attracted to me by my mind. They're attracted by what I
don't mind... Gypsy Rose Lee

Douglas C. Schmidt

unread,
Apr 6, 2001, 8:21:24 AM4/6/01
to
Hi Manoj,

>> Understood. Given that, permit me to turn my question around: What
>> is the canonical way to detect the end-of-file marker using
>> ACE_Pipe on NT?

On NT, ACE_Pipe is implemented by an Internet-domain socket in
"loopback" mode. Thus, if you get back a 0 or -1 from a recv() on the
read_handle() than that indicates EOF.

>> I tried reading through ace/Pipe.cpp, but got lost in the
>> ACE_SOCK_Acceptor/Connector bits in the win32 code.

I recommend you read the paper at

http://www.cs.wustl.edu/~schmidt/PDF/IPC_SAP-92.pdf

for info on how the ACE socket wrappers work. It's *really* easy once
you understand the patterns. Speaking of which, check out the
Acceptor/Connector and Wrapper Facade patterns in POSA2
<www.cs.wustl.edu/~schmidt/POSA/> for an even better description.

0 new messages