Sigaction - przepięcie new action na old action

0

Hej. Mam taki problem - chciałbym wysyłać do procesu sygnał SIGUSR1 i za pierwszym razem chciałbym przechwycić go za pomoca new_action a po jego otrzymaniu tak przepiąć hendlera, żeby już zawsze był obsługiwany przez old_action. Chodzi o prezentację zastosowania mechanizmu z old_action. Czy może ktoś mi z tym pomóc, bo nie mam już pomysłów :(

Kod:


/* Example of using sigaction() to setup a signal handler with 3 arguments
 * including siginfo_t.
 */
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
 
static void hdl (int sig, siginfo_t *siginfo, void *context)
{
	printf ("New Action: Sending PID: %ld, UID: %ld\n",
			(long)siginfo->si_pid, (long)siginfo->si_uid);
}

static void oldhdl (int sig, siginfo_t *siginfo, void *context)
{
	printf ("Old Action: Sending PID: %ld, UID: %ld\n",
			(long)siginfo->si_pid, (long)siginfo->si_uid);
}
 
int main (int argc, char *argv[])
{
	struct sigaction act;
	struct sigaction oldact;
 
	memset (&act, '\0', sizeof(act));
	memset (&oldact, '\0', sizeof(oldact));
 
	/* Use the sa_sigaction field because the handles has two additional parameters */
	act.sa_sigaction = &hdl;
	oldact.sa_sigaction = &oldhdl;
 
	/* The SA_SIGINFO flag tells sigaction() to use the sa_sigaction field, not sa_handler. */
	act.sa_flags = SA_SIGINFO;
	oldact.sa_flags = SA_SIGINFO;
 
	if (sigaction(SIGUSR1, &act, &oldact) < 0) {
		perror ("sigaction");
		return 1;
	}
 
	while (1)
		sleep (10);
 
	return 0;
}
0

Najprościej to chyba coś w ten desen:

static std::atomic_flag lock = ATOMIC_FLAG_INIT;
static struct sigaction oldact = {0};

static void new_handler(int sig, siginfo_t *siginfo, void *context)
{
   if (lock.test_and_set())
   {
        oldact.sa_sigaction(sig, siginfo, context);
   }
   else
   {
      //Pojedyncza obsluga przez ten handler
      //Tutaj możesz ustawić starego handlera:
      sigaction(SIGUSR1, &oldact, NULL);
      //Albo olac bo od teraz i tak stary handler bedzie wywolywany przez nowego handlera
   }
}

static void old_handler(int sig, siginfo_t *siginfo, void *context)
{
}
...
int main(void)
{
  oldact.sa_sigaction = old_handler;
  oldact.sa_flags = SA_SIGINFO;

  if (sigaction(SIGUSR1, &oldact, NULL) < 0)
  {
    return 1;
  }
  ...
  struct sigaction act = oldact;
  act.sa_sigaction = new_handler;

  if (sigaction(SIGUSR1, &act, NULL) < 0)
  {
    return 1;
  }
  ...
}

sigaction jest na liście funkcji Async-signal-safe, więc można go bezpiecznie wywołać z signal handlera.

BTW nie uzywaj printfa w signal handlerach chyba, że lubisz losowe deadlocki w swoim programie.

1 użytkowników online, w tym zalogowanych: 0, gości: 1