Advanced Programming in UNIX Environment Episode 45

#include "apue.h"

static volatile sig_atomic_t sigflag;
static sigset_t newmask, oldmask,zeromask;

static void sig_usr(int signo)
{
    sigflag=1;
}

void TELL_WAIT(void)
{
    if(signal(SIGUSR1,sig_usr)==SIG_ERR)
        err_sys("signal(SIGUSR1) error");
    if(signal(SIGUSR2,sig_usr)==SIG_ERR)
        err_sys("signal(SIGUSR2) error");
    sigemptyset(&zeromask);
    sigemptyset(&newmask);
    sigaddset(&newmask,SIGUSR1);
    sigaddset(&newmask,SIGUSR2);

    if(sigprocmask(SIG_BLOCK,&newmask, &oldmask)<0)
        err_sys("SIG_BLOCK error");
}

void TELL_PARENT(pid_t pid)
{
    kill(pid,SIGUSR2);
}

void WAIT_PARENT(void)
{
    while(sigflag==0)
        sigsuspend(&zeromask);
    sigflag=0;

    if(sigprocmask(SIG_SETMASK, &oldmask, NULL)<0)
        err_sys("SIG_SETMASK error");
}

void TELL_CHILD(pid_t pid)
{
    kill(pid,SIGUSR1);
}

void WAIT_CHILD(void)
{
    while(sigflag==0)
        sigsuspend(&zeromask);
    sigflag=0;

    if(sigprocmask(SIG_SETMASK,&oldmask,NULL)<0)
        err_sys("SIG_SETMASK error");
}

Routines to allow a parent and child to synchronize

We use the two user-defined signals: SIGUSR1 is sent by the parent to the child, and SIGUSR2 is sent by the child to the parent.

The code to handle this looks similar to the following:

if (intr_flag) /* flag set by our SIGINT handler */
    handle_intr();
if (alrm_flag) /* flag set by our SIGALRM handler */
    handle_alrm(); /* signals occurring in here are lost */
while (read( ... ) < 0) {
    if (errno == EINTR) {
        if (alrm_flag)
            handle_alrm();
        else if (intr_flag)
            handle_intr();
        } else {
            /* some other error */
        }
    } else if (n == 0) {
        /* end of file */
    } else {
        /* process input */
}

What we would like to be able to do is the following sequence of steps, in order.

1.Block SIGINT and SIGALRM.
2.Test the two global variables to see whether either signal has occurred and, if so, handle the condition.
3.Call read (or any other system function) and unblock the two signals, as an
atomic operation.

The sigsuspend function helps us only if step 3 is a pause operation.

abort Function
#include <stdlib.h>

void abort(void);

This function sends the SIGABRT signal to the caller. (Processes should not ignore this signal.) ISO C states that calling abort will deliver an unsuccessful termination notification to the host environment by calling raise(SIGABRT).

ISO C requires that if the signal is caught and the signal handler returns, abort still doesn’t return to its caller. If this signal is caught, the only way the signal handler can’t return is if it calls exit, _exit, _Exit, longjmp, or siglongjmp. (Section 10.15 discusses the differences between longjmp and siglongjmp.) POSIX.1 also specifies that abort overrides the blocking or ignoring of the signal by the process.

The ISO C specification of this function leaves it up to the implementation as to
whether output streams are flushed and whether temporary files (Section 5.13) are deleted. POSIX.1 goes further and allows an implementation to call fclose on open standard I/O streams before terminating if the call to abort terminates the process.

Earlier versions of System V generated the SIGIOT signal from the abort function. Furthermore, it was possible for a process to ignore this signal or to catch it and return from the signal handler, in which case abort returned to its caller.
4.3BSD generated the SIGILL signal. Before doing this, the 4.3BSD function unblocked the signal and reset its disposition to SIG_DFL (terminate with core file). This prevented a process from either ignoring the signal or catching it.
Since most UNIX System implementations of tmpfile call unlink immediately after creating the file, the ISO C warning about temporary files does not usually concern us.

#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

void abort(void)
{
    sigset_t mask;
    struct sigaction action;

    sigaction(SIGABRT, NULL, &action);
    if(action.sa_handler==SIG_IGN)
    {
        action.sa_handler==SIG_DFL;
        sigaction(SIGABRT,&action,NULL);
    }
    if(action.sa_handler==SIG_DFL)
        fflush(NULL);
    
    sigfillset(&mask);
    sigdelset(&mask, SIGABRT);
    sigprocmask(SIG_SETMASK,&mask, NULL);
    kill(getpid(),SIGABRT);

    fflush(NULL);
    action.sa_handler=SIG_DFL;
    sigaction(SIGABRT,&action,NULL);
    sigprocmask(SIG_SETMASK,&mask,NULL);
    kill(getpid(),SIGABRT);
    return 1;
}

Implementation of POSIX.1 abort

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值