This is the mail archive of the cygwin mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Problem: SIGCONT handler is not called (Cygwin or Bash problem ?)


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/


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]