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
#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;
}
--
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/

Reply via email to