Re: XForms: Can't get pipes to work right, totally confused.....

Steve Lamont (spl@szechuan.ucsd.edu)
Sat, 21 Aug 99 17:15:02 PDT

# To subscribers of the xforms list from spl@szechuan.ucsd.edu (Steve Lamont) :

> >How do you turn off the echo between pipes[0] and pipes[1] at the
> >parent????

As someone else indicated, you need a pipe per direction.

> >Why is the child not piping back to the parent when it uses puts() or
> >printf()??? This means that you cannot get the output of an app piped
> >back unless that app dows not use puts()'s and printf()'s.... How can
> >tht be quarantied????

Use fflush() to cause the buffer to be flushed. Otherwise, the data
will be buffered until the buffer is full and then flushed.

Here's a bit of code that is part of a larger application. It opens a
single pipe that is used to communicate the temperature of a heat
exchanger (part of a chilled CCD image acquisition system) from the
child to the parent. All the Chiller...() stuff is, of course,
related to the heat exchanger's operation, but has been left in to
give an idea of how this interfaces with an application.

The following somewhat stripped down code does a fork() and, if the
process is the child (case 0), it initializes and connects to the
chiller, then periodically polls the device, requesting its
temperature, and then sending a message to the parent:

pid_t pid;
int fd[2];

if ( pipe( fd ) == 0 ) { /* create a pipe */

switch ( pid = fork() ) { /* Fork a process to monitor */

case 0: { /* child */

Chiller chiller_ptr;

chiller_ptr = ChillerInitialize();
if ( ChillerConnect( chiller_ptr ) == ChillerErrorNone ) {

FILE *f = fdopen( fd[1], "w" );

signal( SIGINT, catch_chiller_shutdown_signal );
signal( SIGUSR1, catch_chiller_shutdown_signal );
signal( SIGPIPE, catch_parent_died_signal );

close( fd[0] ); /* close the read side of the pipe */

if ( ChillerTurnOn( chiller_ptr ) )
report_chiller_error( chiller_ptr, f );

while ( !chiller_exit ) { /* true if the parent
goes away */
double temperature;

ChillerGetTemperature( chiller_ptr,
&temperature );
fprintf( f, "T %g\n", temperature );
fflush( f ); /* Immediately flush info to parent */

usleep( chiller_sleep_microsec );

}
exit( 0 );

}
exit( 1 );

}
case -1: {

NCCERROR( status = NCCErrorSystemError,
"Forking chiller handler process." );
break;

}
default: {

close( fd[1] ); /* Close the write side. */
break;

}

}

} else
NCCERROR( status = NCCErrorSystemError,
"Failed to create chiller control pipe!" );
[...]

The following bit of XForms code registers an IO callback. It also
registers a signal callback in case the monitoring process dies
unexpectedly:

fl_add_io_callback( fd[0], /* The read descriptor */
FL_READ,
chiller_data_cb,
context_ptr );
fl_add_signal_callback( SIGCHLD, chiller_died_cb, context_ptr );

This is the data callback:

void chiller_data_cb( int fd, void *data )

{

ContextP context_ptr = ( ContextP ) data;
char buffer[BUFSIZE];
int n;

n = read( fd, buffer, sizeof( buffer ) - 1 );

if ( n == -1 )
errno_error( "Error reading from chiller!" );
else {

double temp;

sscanf( buffer, "%*c %lf", &temp );
report_chiller_temp( context_ptr, temp );

}

}

The ContextP stuff is application related data and not of interest
here.

As you can see, I don't do bidirectional communication but it would be
easy to do so given the framework shown above.

spl
_________________________________________________
To unsubscribe, send the message "unsubscribe" to
xforms-request@bob.usuhs.mil or see
http://bob.usuhs.mil/mailserv/xforms.html
XForms Home Page: http://bragg.phys.uwm.edu/xforms
List Archive: http://bob.usuhs.mil/mailserv/list-archives/