Mail Archives: cygwin/2004/09/06/02:16:19
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/
- Raw text -