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