monotone

monotone Mtn Source Tree

Root/unix/main.cc

1// Copyright (C) 2006 Zack Weinberg <zackw@panix.com>
2// Based on code by Graydon Hoare and contributors
3// Originally derived from execution_monitor.cpp, a part of boost.
4//
5// This program is made available under the GNU GPL version 2.0 or
6// greater. See the accompanying file COPYING for details.
7//
8// This program is distributed WITHOUT ANY WARRANTY; without even the
9// implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
10// PURPOSE.
11
12
13// This file provides the outermost main(), but it is probable that you want
14// to look at monotone.cc for cpp_main(), where the real program logic
15// begins. The purpose of this file is to hide all the nastiness involved
16// in trapping and responding to operating-system-level hard error reports.
17//
18// On Unix, what we care about is signals. Signals come in two varieties:
19// those that indicate a catastrophic program error (SIGSEGV etc) and those
20// that indicate a user-initiated cancellation of processing (SIGINT etc).
21// In a perfect universe, we could simply throw an exception from the signal
22// handler and leave error reporting up to catch clauses out in main().
23// This does work for some platforms and some subset of the signals we care
24// about, but not enough of either to be worth doing. Also, for signals of
25// the first variety, enough program state may already have been mangled
26// that running destructors is unsafe.
27//
28// Furthermore, it is not safe to do anything "complicated" in a signal
29// handler. "Complicated" is a hard thing to define, but as a general rule,
30// accessing global variables of type 'volatile sig_atomic_t' is safe, and
31// so is making some (but not all) system calls, and that's about it. It is
32// known that write, signal, raise, setrlimit, and _exit [ *not* exit ] are
33// safe system calls [ even though some of them are actually libc wrappers ].
34// Two things that are definitely *not* safe are allocating memory and using
35// stdio or iostreams. strsignal() should be safe, but it is conceivable it
36// would allocate memory; should it cause trouble, out it goes.
37
38
39#include "base.hh"
40#include <signal.h>
41#include <time.h>
42#include <string.h>
43#include <sys/resource.h>
44#include <unistd.h>
45
46static char const * argv0;
47
48// a convenient wrapper
49inline void
50write_str_to_stderr(const char *s)
51{
52 write(2, s, strlen(s));
53}
54
55// this message should be kept consistent with ui.cc::fatal and
56// win32/main.cc::bug_report_message (it is not exactly the same)
57static void
58bug_report_message()
59{
60 write_str_to_stderr("\nthis is almost certainly a bug in monotone."
61 "\nplease send this error message, the output of '");
62 write_str_to_stderr(argv0);
63 write_str_to_stderr(" version --full',"
64 "\nand a description of what you were doing to "
65 PACKAGE_BUGREPORT "\n");
66}
67
68// this handler takes signals which would normally trigger a core
69// dump, and prints a slightly more helpful error message first.
70static void
71bug_signal(int signo)
72{
73 write_str_to_stderr(argv0);
74 write_str_to_stderr(": fatal signal: ");
75 write_str_to_stderr(strsignal(signo));
76 bug_report_message();
77 write_str_to_stderr("do not send a core dump, but if you have one, "
78 "\nplease preserve it in case we ask you for "
79 "information from it.\n");
80
81 raise(signo);
82 // The signal has been reset to the default handler by SA_RESETHAND
83 // specified in the sigaction() call, but it's also blocked; it will be
84 // delivered when this function returns.
85}
86
87// User interrupts cause abrupt termination of the process as well, but do
88// not represent a bug in the program. We do intercept the signal in order
89// to print a pretty message. Note that this relies on sqlite's auto-
90// recovery feature (see <http://sqlite.org/lockingv3.html>, notably section
91// 'The Rollback Journal').
92static void
93interrupt_signal(int signo)
94{
95 write_str_to_stderr(argv0);
96 write_str_to_stderr(": operation canceled: ");
97 write_str_to_stderr(strsignal(signo));
98 write_str_to_stderr("\n");
99 raise(signo);
100 // The signal has been reset to the default handler by SA_RESETHAND
101 // specified in the sigaction() call, but it's also blocked; it will be
102 // delivered when this function returns.
103}
104
105// Signals that we handle can indicate either that there is a real bug
106// (bug_signal), or that we should cancel processing in response to an
107// external event (interrupt_signal).
108static const int bug_signals[] = {
109 SIGQUIT, SIGILL, SIGABRT, SIGFPE, SIGSEGV, SIGBUS, SIGSYS, SIGTRAP
110};
111#define bug_signals_len (sizeof bug_signals / sizeof bug_signals[0])
112static const int interrupt_signals[] = {
113 SIGHUP, SIGINT, SIGPIPE, SIGTERM
114};
115#define interrupt_signals_len (sizeof interrupt_signals \
116 / sizeof interrupt_signals[0])
117
118
119// This file defines the real main(). It just sets up signal
120// handlers, and then calls cpp_main(), which is in monotone.cc.
121
122extern int
123cpp_main(int argc, char ** argv);
124
125int
126main(int argc, char ** argv)
127{
128 struct sigaction bug_signal_action;
129 struct sigaction interrupt_signal_action;
130 size_t i;
131
132 argv0 = argv[0];
133
134 bug_signal_action.sa_flags = SA_RESETHAND;
135 bug_signal_action.sa_handler = &bug_signal;
136 sigemptyset(&bug_signal_action.sa_mask);
137 for (i = 0; i < bug_signals_len; i++)
138 sigaddset(&bug_signal_action.sa_mask, bug_signals[i]);
139 for (i = 0; i < bug_signals_len; i++)
140 sigaction(bug_signals[i], &bug_signal_action, 0);
141
142 interrupt_signal_action.sa_flags = SA_RESETHAND;
143 interrupt_signal_action.sa_handler = &interrupt_signal;
144 sigemptyset(&interrupt_signal_action.sa_mask);
145 for (i = 0; i < interrupt_signals_len; i++)
146 sigaddset(&interrupt_signal_action.sa_mask, interrupt_signals[i]);
147 for (i = 0; i < interrupt_signals_len; i++)
148 sigaction(interrupt_signals[i], &interrupt_signal_action, 0);
149
150 return cpp_main(argc, argv);
151}
152
153// Local Variables:
154// mode: C++
155// fill-column: 76
156// c-file-style: "gnu"
157// indent-tabs-mode: nil
158// End:
159// vim: et:sw=2:sts=2:ts=2:cino=>2s,{s,\:s,+s,t0,g0,^-2,e-2,n-2,p2s,(0,=s:

Archive Download this file

Branches

Tags

Quick Links:     www.monotone.ca    -     Downloads    -     Documentation    -     Wiki    -     Code Forge    -     Build Status