[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
new module 'sigpipe-die'
From: |
Bruno Haible |
Subject: |
new module 'sigpipe-die' |
Date: |
Sun, 31 Aug 2008 16:17:15 +0200 |
User-agent: |
KMail/1.5.4 |
The discussion around SIGPIPE (on this list and on bug-coreutils) around
2008-06-30 convinced me that in general the reasonable reaction on SIGPIPE is:
- if the program only produces output to stdout, then the default behaviour
(terminate the process without an error message) is the right thing;
- if the program also does side effects, then the program should either exit
with an error message or continue the operation, ignoring the SIGPIPE.
For the latter case, an ad-hoc coding is necessary. But for the former case,
it's possible to write the code once only. I'm adding a module 'sigpipe-die'
for this purpose, similar to 'xalloc-die'.
Comments welcome, as always.
2008-08-31 Bruno Haible <address@hidden>
New module 'sigpipe-die'.
* modules/sigpipe-die: New file.
* lib/sigpipe-die.h: New file.
* lib/sigpipe-die.c: New file.
* MODULES.html.sh (Signal handling): Add sigpipe-die.
========================== modules/sigpipe-die =============================
Description:
Report a SIGPIPE signal and exit.
Files:
lib/sigpipe-die.h
lib/sigpipe-die.c
Depends-on:
error
gettext-h
exitfail
sigprocmask
sigaction
configure.ac:
Makefile.am:
lib_SOURCES += sigpipe-die.h sigpipe-die.c
Include:
"sigpipe-die.h"
License:
GPL
Maintainer:
Bruno Haible
=========================== lib/sigpipe-die.h ==============================
/* Report a SIGPIPE signal and exit.
Copyright (C) 2008 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* Written by Bruno Haible <address@hidden>, 2008. */
/* SIGPIPE is the signal sent to a process calling write() on a pipe with no
readers. Together with the signal, the write() call is terminated with
return value -1, errno = EPIPE. Note that SIGPIPE is a *synchronous*
signal: it occurs only during write(), without delay (unless blocked).
The default reaction on SIGPIPE, namely terminating the process without
an error message, is suitable for programs which only produce output to
standard output and don't have side effects.
When a program has side effects, other than writing to standard output, the
suitable behaviour is either
(a) to exit with an error message
or - in certain cases, for example when writing to subprocesses -
(b) to continue the operation without writing to the pipe/socket with
no readers.
This file provides support for (a).
For (b), the program needs to know which of the output file descriptors
has no readers. This is usually implemented by blocking the SIGPIPE signal
and handling an EPIPE error indicator in all affected library calls
(write(), send(), fwrite(), fflush(), fclose(), etc.). */
#ifndef _SIGPIPE_DIE_H
#define _SIGPIPE_DIE_H
#ifdef __cplusplus
extern "C" {
#endif
# ifndef __attribute__
# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8)
# define __attribute__(x)
# endif
# endif
# ifndef ATTRIBUTE_NORETURN
# define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__))
# endif
/* Emit an error message indicating a SIGPIPE signal, and terminate the
process with an error code. */
extern void sigpipe_die (void) ATTRIBUTE_NORETURN;
/* Install a SIGPIPE handler that invokes PREPARE_DIE and then emits an
error message and exits. PREPARE_DIE may be NULL, meaning a no-op. */
extern void install_sigpipe_die_handler (void (*prepare_die) (void));
#ifdef __cplusplus
}
#endif
#endif /* _SIGPIPE_DIE_H */
=========================== lib/sigpipe-die.c ==============================
/* Report a SIGPIPE signal and exit.
Copyright (C) 2008 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* Written by Bruno Haible <address@hidden>, 2008. */
#include <config.h>
/* Specification. */
#include "sigpipe-die.h"
#include <signal.h>
#include <stdlib.h>
#include "error.h"
#include "exitfail.h"
#include "gettext.h"
#define _(msgid) gettext (msgid)
void
sigpipe_die (void)
{
error (exit_failure, 0, "%s",
_("error writing to a closed pipe or socket"));
/* Ensure that this function really does not return. */
abort ();
}
static void (*prepare_die_hook) (void);
/* This is the signal handler for SIGPIPE. It is invoked synchronously,
therefore it can make library calls to malloc(), gettext(), exit() etc. -
although in general it is undefined behaviour to do such calls from
within signal handlers. */
static void
sigpipe_die_handler (int sig)
{
if (prepare_die_hook != NULL)
(*prepare_die_hook) ();
sigpipe_die ();
}
void
install_sigpipe_die_handler (void (*prepare_die) (void))
{
prepare_die_hook = prepare_die;
/* Install the handler. */
{
struct sigaction action;
action.sa_handler = sigpipe_die_handler;
action.sa_flags = 0;
sigemptyset (&action.sa_mask);
if (sigaction (SIGPIPE, &action, NULL) >= 0)
{
/* Unblock the signal (just in case). This is needed because if the
signal was blocked in the parent process, it is also blocked in
this process: the mask of blocked signals is inherited across
fork/exec (except for SIGCHLD). */
sigset_t sigpipe_set;
sigemptyset (&sigpipe_set);
sigaddset (&sigpipe_set, SIGPIPE);
sigprocmask (SIG_UNBLOCK, &sigpipe_set, NULL);
}
}
}
============================================================================
*** MODULES.html.sh.orig 2008-08-31 16:10:39.000000000 +0200
--- MODULES.html.sh 2008-08-31 15:59:53.000000000 +0200
***************
*** 2390,2395 ****
--- 2390,2396 ----
func_module c-stack
func_module libsigsegv
func_module sig2str
+ func_module sigpipe-die
func_end_table
element="Internationalization functions"
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- new module 'sigpipe-die',
Bruno Haible <=