xref: /illumos-gate/usr/src/cmd/sgs/libld/common/exit.c (revision 89c3ee43936b470cda207cc4610e2598b2fc85e3)
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 2009 Sun Microsystems, Inc.  All rights reserved.
27  * Use is subject to license terms.
28  */
29 
30 /*
31  * Utility functions
32  */
33 #include	<unistd.h>
34 #include	<signal.h>
35 #include	<locale.h>
36 #include	<string.h>
37 #include	"msg.h"
38 #include	"_libld.h"
39 
40 /*
41  * Exit after cleaning up.
42  */
43 int
44 ld_exit(Ofl_desc *ofl)
45 {
46 	/*
47 	 * If we have created an output file remove it.
48 	 */
49 	if ((ofl->ofl_fd > 0) && ((ofl->ofl_flags1 & FLG_OF1_NONREG) == 0))
50 		(void) unlink(ofl->ofl_name);
51 
52 	/*
53 	 * Inform any support library that the link-edit has failed.
54 	 */
55 	ld_sup_atexit(ofl, 1);
56 
57 	/*
58 	 * Wrap up debug output file if one is open
59 	 */
60 	dbg_cleanup();
61 
62 	return (1);
63 }
64 
65 /*
66  * Establish the signals we're interested in, and the handlers that need to be
67  * reinstalled should any of these signals occur.
68  */
69 typedef struct {
70 	int	signo;
71 	void (*	defhdl)();
72 } Signals;
73 
74 static Signals signals[] = {
75 	{ SIGHUP,	SIG_DFL },
76 	{ SIGINT,	SIG_IGN },
77 	{ SIGQUIT,	SIG_DFL },
78 	{ SIGBUS,	SIG_DFL },
79 	{ SIGTERM,	SIG_IGN },
80 	{ 0,		0 } };
81 
82 static Ofl_desc	*Ofl = 0;
83 
84 /*
85  * Define our signal handler.
86  */
87 static void
88 /* ARGSUSED2 */
89 handler(int sig, siginfo_t *sip, void *utp)
90 {
91 	struct sigaction	nact;
92 	Signals *		sigs;
93 
94 	/*
95 	 * Reset all ignore handlers regardless of how we got here.
96 	 */
97 	nact.sa_handler = SIG_IGN;
98 	nact.sa_flags = 0;
99 	(void) sigemptyset(&nact.sa_mask);
100 
101 	for (sigs = signals; sigs->signo; sigs++) {
102 		if (sigs->defhdl == SIG_IGN)
103 			(void) sigaction(sigs->signo, &nact, NULL);
104 	}
105 
106 	/*
107 	 * The model for creating an output file is to ftruncate() it to the
108 	 * required size and mmap() a mapping into which the new contents are
109 	 * written.  Neither of these operations guarantee that the required
110 	 * disk blocks exist, and should we run out of disk space a bus error
111 	 * is generated.
112 	 * Other situations have been reported to result in ld catching a bus
113 	 * error (one instance was a stale NFS handle from an unstable server).
114 	 * Thus we catch all bus errors and hope we can decode a better error.
115 	 */
116 	if ((sig == SIGBUS) && sip && Ofl->ofl_name) {
117 		eprintf(Ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_FIL_INTERRUPT),
118 		    Ofl->ofl_name, strerror(sip->si_errno));
119 	}
120 	/*
121 	 * This assert(0) causes DEBUG enabled linkers to produce a core file.
122 	 */
123 	if ((sig != SIGHUP) && (sig != SIGINT))
124 		assert(0);
125 
126 	exit(ld_exit(Ofl));
127 }
128 
129 /*
130  * Establish a signal handler for all signals we're interested in.
131  */
132 void
133 ld_init(Ofl_desc *ofl)
134 {
135 	struct sigaction	nact, oact;
136 	Signals *		sigs;
137 
138 	Ofl = ofl;
139 
140 	/*
141 	 * For each signal we're interested in set up a signal handler that
142 	 * insures we clean up any output file we're in the middle of creating.
143 	 */
144 	nact.sa_sigaction = handler;
145 	(void) sigemptyset(&nact.sa_mask);
146 
147 	for (sigs = signals; sigs->signo; sigs++) {
148 		if ((sigaction(sigs->signo, NULL, &oact) == 0) &&
149 		    (oact.sa_handler != SIG_IGN)) {
150 			nact.sa_flags = SA_SIGINFO;
151 			if (sigs->defhdl == SIG_DFL)
152 				nact.sa_flags |= (SA_RESETHAND | SA_NODEFER);
153 			(void) sigaction(sigs->signo, &nact, NULL);
154 		}
155 	}
156 }
157