delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/2003/12/23/11:50:09

X-Authentication-Warning: delorie.com: mail set sender to djgpp-bounces using -f
Message-ID: <22ca01c3c974$aa833260$0600000a@broadpark.no>
From: "Gisle Vanem" <giva AT bgnett DOT no>
To: "Eli Zaretskii" <eliz AT elta DOT co DOT il>
Cc: "djgpp" <djgpp AT delorie DOT com>
References: <207a01c3c8c6$26445c80$0600000a AT broadpark DOT no> <uisk7irn3 DOT fsf AT elta DOT co DOT il>
Subject: Re: pending SIGALRM
Date: Tue, 23 Dec 2003 17:49:00 +0100
MIME-Version: 1.0
X-Priority: 3
X-MSMail-Priority: Normal
X-Mailer: Microsoft Outlook Express 6.00.2800.1158
X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1165
Reply-To: djgpp AT delorie DOT com

> No, it says that "alarm(0)" ``cancels any pending alarm''.  Note that
> it doesn't say SIGALRM, just ``alarm''.  This means that a signal that
> was already raised won't be affected. 

Okay, thank for explaining that.

> Clearing __sigprocmask_pending_signals was not implemented, as I'm
> not sure we should do that.  Do other systems (e.g., GNU/Linux) clear
> the pending SIGALRM when `alarm(0)' is called?  If they do, we
> probably should do that as well.

I'm not sure. I just trying to support EINTR for e.g. recvfrom()
in the Watt-32 tcp/ip stack. As I understand other stack do
(BSD/Linux), they return -1 and sets errno=EINTR on a SIGALRM. 
My problem is that I need to block the SIGALRM from calling 
other socket functions again while I'm waiting in my loops. 
Otherwise this could cause problems (not everything is reentrant).

I first tried to catch and re-raise SIGALRM same as other signals 
(SIGINT, SIGPIPE etc.), but failed in mysterious ways. So I've 
done it something like this:

  if (sock_sig_setup() < 0) {
    errno = EINTR;
    return -1;
  }
  /* .. do the lengthy stuff here .. */

  sock_sig_restore();
  return rc;  
}
....

static sigset_t old_mask, new_mask;

static void block_sigalrm (void)
{
  sigemptyset (&new_mask);
  sigaddset (&new_mask, SIGALRM);
  sigprocmask (SIG_SETMASK, &new_mask, &old_mask);
}

void sock_sig_restore (int sig)
{
  sigset_t pending;
  if (sigpending(&pending) == 0 &&
      sigismember(&pending,SIGALRM) == 1) &&
      sigprocmask(SIG_UNBLOCK, &new_mask, &old_mask))
    ;  /* calls the alarm() handler now when it's safe */
  else if (sig)
     ...  /* raise() other signals if caught */
}

int sock_sig_setup()
{
  int sig;

  /* sig_catch() longjmp() on a catch */
  signal (SIGINT, sig_catch);   
  block_sigalrm();
  if ((sig = setjmp(jbuf)) != 0)  {
     sock_sig_restore (sig);
     return -1;
  }
  return 0;     
}

I'm not sure I should use SIG_SETMASK on all signals or
only on SIGALRM. Or use the same masking technique for all 
signals. Is there a benefit doing that instead of catching
and reraising the signals (besides portability) ?

>    The DJGPP implementation only records a single occurrence of any given
>    signal, so when the signal is unblocked, its handler will be called at
>    most once.

Suites me fine. Wouldn't have to handle multiple blocked signals.

--gv

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019