Hang problem related to signals and process priority
Ivan Szanto
szivan@bitbybit-is.nl
Mon Mar 4 03:13:00 GMT 2002
Hello cywin guru,
Maybe you can help me with the following problem.
We are running Cygwin version 1.3.10 on Windows NT.
We use sigaction to redirect the SIGIO signal to our
own signal handler in a client/server app.
When running several processes of the same client program
in the background, a couple of them seem to hang.
It is interesting that this problem does not surface when
we have all those processes running in the foreground or
when we start them using "cmd start /high ..."
Please find attached the relevant code for reproducing
the problem. It is a client program that tries to connect
to a telnetd. It expects the machine name where telnetd is
running as well as the repeat count for the send loop.
I reproduced the problem as follows
1. opened an xterm with a bash
2. in the xterm I typed the following
for i in 1 2 3
do
./a.exe localhost 300 &
done
The result was that one process did well, but the other two hanged.
Is this behavior related to a known CYGWIN problem?
Do you think we can change our code in some way to avoid this problem?
We will greatly appreciate your expert advice on this matter.
Greetings,
Ivan
-------------- next part --------------
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <string.h>
#include <signal.h>
int global_int;
void
handle_signal(int a)
{
global_int = 1;
}
int
set_mode(int socknum, int mode)
{
int real_mode;
int flags, yes = 1; // yes actually is needed for CYGWIN
real_mode = mode & (FASYNC + FNDELAY);
flags = fcntl (socknum, F_GETFL);
if (flags == -1)
{ perror("GETFL failed"); exit(0); }
#ifdef __CYGWIN__
flags &= ~(FASYNC + O_NONBLOCK);
#else
flags &= ~(FASYNC + FNDELAY);
#endif
flags |= real_mode;
#ifndef __CYGWIN__
// not supported by cygnus B20.1
if (mode & FASYNC)
{
if (fcntl (socknum, F_SETOWN, getpid ()) == -1)
{ perror("SETOWN failed"); exit(0); }
}
#endif // ! __CYGWIN__ //
if (fcntl (socknum, F_SETFL, flags) == -1)
{ perror("SETFL failed"); exit(0); }
#ifdef __CYGWIN__
if (mode & FASYNC)
{
if (ioctl (socknum, FIOASYNC, &yes) == -1)
{ perror("FIOASYNC failed"); exit(0); }
}
#endif // __CYGWIN__ //
}
int
main(int argc, char *argv[])
{
int socknum;
char host_buffer[100];
struct hostent * host_entry;
struct sockaddr_in * address;
struct sigaction action;
sigset_t block_mask;
int i,n,wait;
void * memory;
if ( argc < 3 )
{ printf("need a hostname and a repeat count\n"); exit(0); }
strncpy(host_buffer, argv[1], 100);
n = atoi(argv[2]);
if ( n < 1 )
{ printf("count %d is not ok\n", n); exit(0); }
/* allocate socket and connect to server */
socknum = socket(AF_INET, SOCK_STREAM, 0);
if ( ! socknum )
{ perror("socknum is 0"); exit(0); }
host_entry = gethostbyname (host_buffer);
if (! host_entry)
{ perror("could not get host entry"); exit(0); }
address = (struct sockaddr_in *)
calloc (1, sizeof (struct sockaddr_in));
if (! address )
{ perror("could not alloc address"); exit(0); }
address -> sin_family = AF_INET;
memcpy ((char *) &(address -> sin_addr),
(char *) host_entry -> h_addr,
host_entry -> h_length);
address -> sin_port = htons(23);
if (connect (socknum, (struct sockaddr *)address, sizeof (struct sockaddr_in))
== -1)
{ perror("connect failed"); exit(0); }
/* sigaction */
global_int = 0;
sigemptyset (&block_mask);
sigaddset (&block_mask, SIGINT);
sigaddset (&block_mask, SIGQUIT);
sigaddset (&block_mask, SIGTSTP);
sigaddset (&block_mask, SIGIO);
// note that SA_RESTART is not supported on cygnus prior to 1.1.8
action.sa_handler = handle_signal;
action.sa_mask = block_mask;
action.sa_flags = SA_RESTART;
if (sigaction (SIGIO, &action, (struct sigaction *) 0) == -1)
{ perror("sigaction failed"); exit(0); }
/* set async mode */
set_mode (socknum, FNDELAY + FASYNC);
for ( i = 0; i < n ; i++ )
{
if ( send (socknum, host_buffer, 1, 0) == -1 )
{ perror("send failed"); exit(0); }
for ( wait = 0; wait < 1000; wait++ )
{
memory = malloc(1000);
if ( !memory )
{ perror("malloc failed"); continue; }
free(memory);
}
}
printf("Everything went ok, global_int is %d!\n", global_int);
return 0;
}
-------------- next part --------------
--
Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple
Bug reporting: http://cygwin.com/bugs.html
Documentation: http://cygwin.com/docs.html
FAQ: http://cygwin.com/faq/
More information about the Cygwin
mailing list