1 /* Handle faults in the signal thread.
2 Copyright (C) 1994,1995,1996,1997,2002,2005
3 Free Software Foundation, Inc.
4 This file is part of the GNU C Library.
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with the GNU C Library; if not, write to the Free
18 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
22 #include <hurd/signal.h>
23 #include "hurdfault.h"
28 #include <thread_state.h>
29 #include "faultexc_server.h" /* mig-generated header for our exc server. */
32 jmp_buf _hurdsig_fault_env
;
33 struct hurd_signal_preemptor _hurdsig_fault_preemptor
= {0};
35 /* XXX temporary to deal with spelling fix */
36 weak_alias (_hurdsig_fault_preemptor
, _hurdsig_fault_preempter
)
38 static mach_port_t forward_sigexc
;
41 _hurdsig_fault_catch_exception_raise (mach_port_t port
,
44 #ifdef EXC_MASK_ALL /* New interface flavor. */
45 exception_type_t exception
,
46 exception_data_t code
,
47 mach_msg_type_number_t codeCnt
48 #else /* Vanilla Mach 3.0 interface. */
50 integer_t code
, integer_t subcode
55 struct hurd_signal_detail d
;
57 if (port
!= forward_sigexc
||
58 thread
!= _hurd_msgport_thread
|| task
!= __mach_task_self ())
59 return EPERM
; /* Strange bogosity. */
63 assert (codeCnt
>= 2);
65 d
.exc_subcode
= code
[1];
68 d
.exc_subcode
= subcode
;
71 /* Call the machine-dependent function to translate the Mach exception
72 codes into a signal number and subcode. */
73 _hurd_exception2signal (&d
, &signo
);
75 return HURD_PREEMPT_SIGNAL_P (&_hurdsig_fault_preemptor
, signo
, d
.code
)
80 /* XXX New interface flavor has additional RPCs that we could be using
81 instead. These RPCs roll a thread_get_state/thread_set_state into
82 the message, so the signal thread ought to use these to save some calls.
85 _hurdsig_fault_catch_exception_raise_state
87 exception_type_t exception
,
88 exception_data_t code
,
89 mach_msg_type_number_t codeCnt
,
91 thread_state_t old_state
,
92 mach_msg_type_number_t old_stateCnt
,
93 thread_state_t new_state
,
94 mach_msg_type_number_t
*new_stateCnt
)
101 _hurdsig_fault_catch_exception_raise_state_identity
102 (mach_port_t exception_port
,
105 exception_type_t exception
,
106 exception_data_t code
,
107 mach_msg_type_number_t codeCnt
,
109 thread_state_t old_state
,
110 mach_msg_type_number_t old_stateCnt
,
111 thread_state_t new_state
,
112 mach_msg_type_number_t
*new_stateCnt
)
120 #ifdef NDR_CHAR_ASCII /* OSF Mach flavors have different names. */
121 # define mig_reply_header_t mig_reply_error_t
129 mach_msg_header_t head
;
132 mig_reply_header_t reply
;
133 extern int _hurdsig_fault_exc_server (mach_msg_header_t
*,
134 mach_msg_header_t
*);
136 /* Wait for the exception_raise message forwarded by the proc server. */
138 if (__mach_msg (&request
.head
, MACH_RCV_MSG
, 0,
139 sizeof request
, forward_sigexc
,
140 MACH_MSG_TIMEOUT_NONE
, MACH_PORT_NULL
)
142 __libc_fatal ("msg receive failed on signal thread exc\n");
144 /* Run the exc demuxer which should call the server function above.
145 That function returns 0 if the exception was expected. */
146 _hurdsig_fault_exc_server (&request
.head
, &reply
.Head
);
147 if (reply
.Head
.msgh_remote_port
!= MACH_PORT_NULL
)
148 __mach_msg (&reply
.Head
, MACH_SEND_MSG
, reply
.Head
.msgh_size
,
149 0, MACH_PORT_NULL
, MACH_MSG_TIMEOUT_NONE
, MACH_PORT_NULL
);
150 if (reply
.RetCode
== MIG_BAD_ID
)
151 __mach_msg_destroy (&request
.head
);
154 __libc_fatal ("BUG: unexpected fault in signal thread\n");
156 _hurdsig_fault_preemptor
.signals
= 0;
157 longjmp (_hurdsig_fault_env
, 1);
160 static char faultstack
[1024];
162 /* Send exceptions for the signal thread to the proc server.
163 It will forward the message on to our message port,
164 and then restore the thread's state to code which
165 does `longjmp (_hurd_sigthread_fault_env, 1)'. */
168 _hurdsig_fault_init (void)
171 struct machine_thread_state state
;
174 /* Allocate a port to receive signal thread exceptions.
175 We will move this receive right to the proc server. */
176 err
= __mach_port_allocate (__mach_task_self (),
177 MACH_PORT_RIGHT_RECEIVE
, &sigexc
);
179 err
= __mach_port_allocate (__mach_task_self (),
180 MACH_PORT_RIGHT_RECEIVE
, &forward_sigexc
);
183 /* Allocate a port to receive the exception msgs forwarded
184 from the proc server. */
185 err
= __mach_port_insert_right (__mach_task_self (), sigexc
,
186 sigexc
, MACH_MSG_TYPE_MAKE_SEND
);
189 /* Set the queue limit for this port to just one. The proc server will
190 notice if we ever get a second exception while one remains queued and
191 unreceived, and decide we are hopelessly buggy. */
192 #ifdef MACH_PORT_RECEIVE_STATUS_COUNT
194 const mach_port_limits_t lim
= { mpl_qlimit
: 1 };
195 assert (MACH_PORT_RECEIVE_STATUS_COUNT
== sizeof lim
/ sizeof (natural_t
));
196 err
= __mach_port_set_attributes (__mach_task_self (), forward_sigexc
,
197 MACH_PORT_RECEIVE_STATUS
,
198 (mach_port_info_t
) &lim
,
199 MACH_PORT_RECEIVE_STATUS_COUNT
);
202 err
= __mach_port_set_qlimit (__mach_task_self (), forward_sigexc
, 1);
206 /* This state will be restored when we fault.
207 It runs the function above. */
208 memset (&state
, 0, sizeof state
);
209 MACHINE_THREAD_STATE_SET_PC (&state
, faulted
);
210 MACHINE_THREAD_STATE_SET_SP (&state
, faultstack
, sizeof faultstack
);
214 __proc_handle_exceptions (port
,
216 forward_sigexc
, MACH_MSG_TYPE_MAKE_SEND
,
217 MACHINE_THREAD_STATE_FLAVOR
,
218 (natural_t
*) &state
,
219 MACHINE_THREAD_STATE_COUNT
));
222 /* Direct signal thread exceptions to the proc server. */
223 #ifdef THREAD_EXCEPTION_PORT
224 err
= __thread_set_special_port (_hurd_msgport_thread
,
225 THREAD_EXCEPTION_PORT
, sigexc
);
226 #elif defined (EXC_MASK_ALL)
227 __thread_set_exception_ports (_hurd_msgport_thread
,
228 EXC_MASK_ALL
& ~(EXC_MASK_SYSCALL
229 | EXC_MASK_MACH_SYSCALL
230 | EXC_MASK_RPC_ALERT
),
232 EXCEPTION_STATE_IDENTITY
,
233 MACHINE_THREAD_STATE
);
235 # error thread_set_exception_ports?
237 __mach_port_deallocate (__mach_task_self (), sigexc
);