Hi,

in the process of porting some software to the Cygwin environment i came
across a problem when trying to install a signal SIGCONT handler.  This is
needed as the program puts the terminal into certain states that need to be
reset/set again when SIGTSTP/SIGCONT signals are received.

My problem is that the SIGCONT handler is never triggered (as it seems to
me).  I could reduce the problem into the following code snippets.  Note
that i have also a testversion using only the Posix calls (sigprocmask,
sigaction) but it behaves identically:  the SIGCONT handler is never called.
I can (in the Posix version) remove the sigaction(SIGCONT,..) after which
the test routine stops at the kill() command after a SIGTSTP.  Sending a
SIGCONT resumes the program after the kill and there i could continue with
the SIGCONT code but this is not really what i want to do (because i want
the SIGCONT also to work after a SIGTERM).

Questions:
1) is there a problem with the SIGCONT handling in CYGWIN ?  Why is it never
called or is SIGCONT not delivered ?
2) what is the signal delivery scheme in Cygwin for SIGCONT i.e. what is
called first after issueing a shell - fg command ?
3) or do i miss something in my code here that would be specific for Cygwin
(i tested it on various other Unix platforms with success) ?

I'm on Cygwin 1.5.10-3,  gcc 3.3.1-3 gcc-core 3.3.3-3, bash 2.05b-16,
platform = Win2000 Professional V5.0 Build 2195 SP4

Testsequence:  gcc prog.c -o prog
                         prog
                         ^Z
                         fg
                         --> bash types prog but the program blocks.


Classic signal version:
----------------------------------------------------------------------------
-------------------

#include <stdlib.h>
#include <stdio.h>              /* IO functions    */
#include <string.h>             /* strlen functions*/
#include <errno.h>              /* file errors     */
#include <signal.h>             /* emulate signals */

/* =================================================================== */
void            signal_handler();
void (*Tstp) (), (*Cont) ();


/* ================================================================ */
int main() {

        int input;
        char buf[3];
        int i;

        Tstp = signal(SIGTSTP, signal_handler); /* ctrl-Z, kill -18 */
        Cont = signal(SIGCONT, SIG_DFL);        /* fg after ^Z, kill -19 */

        /* first get the char in the selected mode */
        printf("Give a char:\n ");
        input = getc(stdin);
        if (input == EOF) printf("Input error\n");

        /* reset signals */
        signal(SIGTSTP, Tstp);  /* ctrl-Z */
        signal(SIGCONT, Cont);  /* fg after ^Z */
}

/* ================================================================ */
void signal_handler(int sig)
{
        int             send_sig=0;     /* signal to be sent */

        sigset_t mask;

printf("\nSIGTSTP = %d, SIGCONT = %d, signal = %d \n",SIGTSTP,SIGCONT,sig);
        switch (sig) {
        case SIGTSTP:
                printf("catching the SIGTSTP\n");
                send_sig = SIGTSTP ;/*STOP;     /* send a suspend signal    */
                signal(sig, SIG_DFL);   /* load default signal mode */
                /* now we will install the SIGCONT handler */
                        if(signal(SIGCONT, signal_handler)==SIG_ERR)
                     printf("Error loading SIGCONT handler... \n");
                                kill(getpid(),send_sig);

                printf("now after the kill....\n");
                break;

                /* this is resumed after a suspend: */
        case SIGCONT:
                printf("catching the SIGCONT\n");
                printf(" Continuing ..... (my_raw.c)\n");
                fflush(stdout);
                signal(sig, signal_handler);    /* keep same signal mode */
                break;
        }

}

----------------------------------------------------------------------------
---------------------

Posix call version:
----------------------------------------------------------------------------
---------------------
#include <stdlib.h>
#include <stdio.h>              /* IO functions    */
#include <string.h>             /* strlen functions */
#include <errno.h>              /* file errors     */
#include <signal.h>             /* emulate signals */
/* =================================================================== */
sigset_t mask_old, mask_new;
struct sigaction Tstp_old, Tstp_new;
struct sigaction Cont_old, Cont_new;
void signal_handler ();
void (*Tstp) (), (*Cont) ();


/* ================================================================ */
int main ()
{

  int input;
  char buf[3];
  int i;

  sigemptyset (&mask_new);
  sigaddset (&mask_new, SIGCONT);
  sigaddset (&mask_new, SIGTSTP);
  sigprocmask (SIG_SETMASK, &mask_new, &mask_old);      /* block signals */

  sigemptyset (&mask_new);
  Tstp_new.sa_handler = signal_handler;
  Tstp_new.sa_mask = mask_new;
  Tstp_new.sa_flags = 0;
  sigaction (SIGTSTP, &Tstp_new, &Tstp_old);    /* install SIGTSTP handler */

  sigprocmask (SIG_SETMASK, &mask_old, NULL);   /*unblock signals again */


  /* first get the char in the selected mode */
  printf ("Give a char:\n ");
  input = getc (stdin);
  if (input == EOF)
    printf ("Input error\n");

  /* reset signals */
}

/* ================================================================ */
void
signal_handler (int sig)
{
  int send_sig = 0;             /* signal to be sent */

  sigset_t mask;

  printf ("\nSIGTSTP = %d, SIGCONT = %d, signal = %d \n", SIGTSTP, SIGCONT,
sig);
  switch (sig)
    {
    case SIGTSTP:
      printf ("catching the SIGTSTP\n");
      send_sig = SIGTSTP;       /*STOP;     /* send a suspend signal    */
      //      /* now we will install the SIGCONT handler */

      sigemptyset (&mask_new);
      sigaddset (&mask_new, SIGTSTP);
      sigaddset (&mask_new, SIGCONT);
      sigprocmask (SIG_SETMASK, &mask_new, NULL);       /* block again */

      sigaction (SIGTSTP, &Tstp_old, NULL);


      sigemptyset (&mask_new);
      Cont_new.sa_handler = signal_handler;
      Cont_new.sa_mask = mask_new;
      Cont_new.sa_flags = 0;
      if (sigaction (SIGCONT, &Cont_new, &Cont_old) != 0)       /* install SIGCONT
handler */
        printf ("Error loading SIGCONT handler\n");

      sigprocmask (SIG_SETMASK, &mask_old, NULL);       /* unblock signals again
*/

      kill (getpid (), send_sig);


      printf ("now after the kill....\n");
      break;

    case SIGCONT:
      /* this is resumed after a suspend: */
      printf ("catching the SIGCONT\n");
      printf (" Continuing ..... (my_raw.c)\n");
      printf ("Don't mind the input error: there comes a longjmp here\n");
      fflush (stdout);
      break;
    }

}

----------------------------------------------------------------------------
-----------------

Rudi Vankemmel


--
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
Problem reports:       http://cygwin.com/problems.html
Documentation:         http://cygwin.com/docs.html
FAQ:                   http://cygwin.com/faq/

Reply via email to