xref: /titanic_41/usr/src/cmd/sgs/libld/common/exit.c (revision 6a634c9dca3093f3922e4b7ab826d7bdf17bf78e)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  *	Copyright (c) 1988 AT&T
24  *	  All Rights Reserved
25  *
26  * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
27  */
28 
29 /*
30  * Utility functions
31  */
32 #include	<unistd.h>
33 #include	<signal.h>
34 #include	<locale.h>
35 #include	<string.h>
36 #include	"msg.h"
37 #include	"_libld.h"
38 
39 /*
40  * Exit after cleaning up.
41  */
42 int
ld_exit(Ofl_desc * ofl)43 ld_exit(Ofl_desc *ofl)
44 {
45 	/*
46 	 * If we have created an output file remove it.
47 	 */
48 	if ((ofl->ofl_fd > 0) && ((ofl->ofl_flags1 & FLG_OF1_NONREG) == 0))
49 		(void) unlink(ofl->ofl_name);
50 
51 	/*
52 	 * Inform any support library that the link-edit has failed.
53 	 */
54 	ld_sup_atexit(ofl, 1);
55 
56 	/*
57 	 * Wrap up debug output file if one is open
58 	 */
59 	dbg_cleanup();
60 
61 	/* If any ERR_GUIDANCE messages were issued, add a summary */
62 	if (ofl->ofl_guideflags & FLG_OFG_ISSUED)
63 		ld_eprintf(ofl, ERR_GUIDANCE, MSG_INTL(MSG_GUIDE_SUMMARY));
64 
65 	return (1);
66 }
67 
68 /*
69  * Establish the signals we're interested in, and the handlers that need to be
70  * reinstalled should any of these signals occur.
71  */
72 typedef struct {
73 	int	signo;
74 	void (*	defhdl)();
75 } Signals;
76 
77 static Signals signals[] = {
78 	{ SIGHUP,	SIG_DFL },
79 	{ SIGINT,	SIG_IGN },
80 	{ SIGQUIT,	SIG_DFL },
81 	{ SIGBUS,	SIG_DFL },
82 	{ SIGTERM,	SIG_IGN },
83 	{ 0,		0 } };
84 
85 static Ofl_desc	*Ofl = NULL;
86 
87 /*
88  * Define our signal handler.
89  */
90 static void
91 /* ARGSUSED2 */
handler(int sig,siginfo_t * sip,void * utp)92 handler(int sig, siginfo_t *sip, void *utp)
93 {
94 	struct sigaction	nact;
95 	Signals *		sigs;
96 
97 	/*
98 	 * Reset all ignore handlers regardless of how we got here.
99 	 */
100 	nact.sa_handler = SIG_IGN;
101 	nact.sa_flags = 0;
102 	(void) sigemptyset(&nact.sa_mask);
103 
104 	for (sigs = signals; sigs->signo; sigs++) {
105 		if (sigs->defhdl == SIG_IGN)
106 			(void) sigaction(sigs->signo, &nact, NULL);
107 	}
108 
109 	/*
110 	 * The model for creating an output file is to ftruncate() it to the
111 	 * required size and mmap() a mapping into which the new contents are
112 	 * written.  Neither of these operations guarantee that the required
113 	 * disk blocks exist, and should we run out of disk space a bus error
114 	 * is generated.
115 	 * Other situations have been reported to result in ld catching a bus
116 	 * error (one instance was a stale NFS handle from an unstable server).
117 	 * Thus we catch all bus errors and hope we can decode a better error.
118 	 */
119 	if ((sig == SIGBUS) && sip && Ofl->ofl_name) {
120 		ld_eprintf(Ofl, ERR_FATAL, MSG_INTL(MSG_FIL_INTERRUPT),
121 		    Ofl->ofl_name, strerror(sip->si_errno));
122 	}
123 	/*
124 	 * This assert(0) causes DEBUG enabled linkers to produce a core file.
125 	 */
126 	if ((sig != SIGHUP) && (sig != SIGINT))
127 		assert(0);
128 
129 	exit(ld_exit(Ofl));
130 }
131 
132 /*
133  * Establish a signal handler for all signals we're interested in.
134  */
135 void
ld_init_sighandler(Ofl_desc * ofl)136 ld_init_sighandler(Ofl_desc *ofl)
137 {
138 	struct sigaction	nact, oact;
139 	Signals *		sigs;
140 
141 	Ofl = ofl;
142 
143 	/*
144 	 * Our heavy use of mmap() means that we are susceptible to
145 	 * receiving a SIGBUS in low diskspace situations. The main
146 	 * purpose of the signal handler is to handle that situation
147 	 * gracefully, so that out of disk errors don't drop a core file.
148 	 *
149 	 * In rare cases, this will prevent us from getting a core from a
150 	 * SIGBUS triggered by an internal alignment error in libld.
151 	 * If -znosighandler is set, return without registering the
152 	 * handler. This is primarily of use for debugging problems in
153 	 * the field, and is not of general interest.
154 	 */
155 	if (ofl->ofl_flags1 & FLG_OF1_NOSGHND)
156 		return;
157 
158 	/*
159 	 * For each signal we're interested in set up a signal handler that
160 	 * insures we clean up any output file we're in the middle of creating.
161 	 */
162 	nact.sa_sigaction = handler;
163 	(void) sigemptyset(&nact.sa_mask);
164 
165 	for (sigs = signals; sigs->signo; sigs++) {
166 		if ((sigaction(sigs->signo, NULL, &oact) == 0) &&
167 		    (oact.sa_handler != SIG_IGN)) {
168 			nact.sa_flags = SA_SIGINFO;
169 			if (sigs->defhdl == SIG_DFL)
170 				nact.sa_flags |= (SA_RESETHAND | SA_NODEFER);
171 			(void) sigaction(sigs->signo, &nact, NULL);
172 		}
173 	}
174 }
175