Signal-driven I/O

Masahiko Shimoda (shimoda@rios.co.jp)
Thu, 15 Oct 1998 11:54:53 +0900


Hello,

I have written a client/server program using libc 5.3.12
on Linux 2.0.33. The server program communicates with
the client via socket. The server executes a python
script ( specified by the client ) in the same process,
and returns the data which have been written to "stdout"
by the script.

When I ran it, the script executed by the server could not
write large data to "stdout".

Then I have written a simple program ( bottom of this message )
which consists of the part of the server program and a dummy
function ( read_and_write() ) instead of the function executes
a python script. In addition, this program writes data to
a file instead of sending data to a client. And I ran it.

If the size of the file "sample.dat" was 65535 bytes and under,
the program terminated with no errors. But the size was over
65535 bytes, the fwrite() call in the read_and_write() failed
and "errno" was set to 512.

##### Write error! ERROR No. : 512

I posted this matter to the list "linux-net", and I was
given advice it is a kernel's bug. If it is a kernel's bug,
are there any patch for solving this problem? Or if this
bug has been already fixed, which version of kernel should
I use?

I thank you in advance for your advice.

Regards,
Masahiko Shimoda

#include <stdio.h>
#ifdef sun
#include <sys/types.h>
#include <stropts.h>
#endif
#include <sys/socket.h>
#include <fcntl.h>
#include <signal.h>
#include <errno.h>
#include <sys/stat.h>

#define INPUT_FILE "sample.dat"
#define OUTPUT_FILE "result.dat"

static void signal_sigpoll( int signo ) ;
static int read_and_write( void ) ;

static int sfd_S[2] ;
static FILE *ofp_S ;

int main( int argc, char argv[] )
{
struct sigaction act ;

ofp_S = fopen( OUTPUT_FILE, "w" ) ;
if( ofp_S == NULL )
{
fprintf( stderr, "fopen() error.\n" ) ;
exit( 1 ) ;
}

if( socketpair( AF_UNIX, SOCK_STREAM, 0, sfd_S ) )
{
fprintf( stderr, "socketpair() error.\n" ) ;
exit( 1 ) ;
}

if( dup2( sfd_S[1], fileno( stdout ) ) < 0 )
{
fprintf( stderr, "dup2() error.\n" ) ;
exit( 1 ) ;
}

#ifdef sun
signal( SIGPOLL, signal_sigpoll ) ;
#else /* linux */
sigaction( SIGPOLL, NULL, &act ) ;
act.sa_handler = signal_sigpoll ;
act.sa_flags = SA_RESTART ;
sigaddset( &act.sa_mask, SIGPOLL ) ;
act.sa_restorer = NULL ;
sigaction( SIGPOLL, &act, NULL ) ;
#endif

#ifdef sun
ioctl( sfd_S[0], I_SETSIG, S_RDNORM ) ;
fcntl( sfd_S[0], F_SETFL, O_NDELAY ) ;
#else /* linux */
fcntl( sfd_S[0], F_SETOWN, getpid() ) ;
fcntl( sfd_S[0], F_SETFL, FASYNC | O_NDELAY ) ;
#endif

read_and_write() ;

fflush( stdout ) ;

fclose( ofp_S ) ;

exit( 0 ) ;
}

static void signal_sigpoll( int signo )
{
char buff[BUFSIZ] ;
int length ;

#ifdef sun
sighold( SIGPOLL ) ;
#endif

length = read( sfd_S[0], buff, BUFSIZ ) ;
while( length > 0 )
{
fwrite( buff, 1, length, ofp_S ) ;
length = read( sfd_S[0], buff, BUFSIZ ) ;
}

#ifdef sun
signal( SIGPOLL, signal_sigpoll ) ;
sigrelse( SIGPOLL ) ;
#endif

return ;
}

static int read_and_write( void )
{
struct stat st_buf ;
FILE *ifp ;
char *buff ;
size_t len ;

if( stat( INPUT_FILE, &st_buf ) )
{
fprintf( stderr, "stat() error.\n" ) ;
return( 1 ) ;
}

buff = ( char * )malloc( st_buf.st_size ) ;
if( buff == NULL )
{
fprintf( stderr, "malloc() error.\n" ) ;
return( 1 ) ;
}

ifp = fopen( INPUT_FILE, "r" ) ;
if( ifp == NULL )
{
fprintf( stderr, "fopen() error.\n" ) ;
return( 1 ) ;
}

fread( ( void * )buff, 1, st_buf.st_size, ifp ) ;

fclose( ifp ) ;

len = fwrite( ( void * )buff, 1, st_buf.st_size, stdout ) ;

if( ferror( stdout ) )
{
fprintf( stderr, "##### Write error! ERROR No. : %d\n", errno ) ;
return( 1 ) ;
}

return( 0 ) ;
}

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/