* exceptions.cc (_cygtls::handle_exceptions): Call new

mmap_is_attached_or_noreserve_page function in case of access violation
	and allow application to retry access on noreserve pages.
	* mmap.cc (mmap_is_attached_or_noreserve_page): Changed from
	mmap_is_attached_page.  Handle also noreserve pages now.  Change
	comment accordingly.
	* winsup.h (mmap_is_attached_or_noreserve_page): Declare instead of
	mmap_is_attached_page.
This commit is contained in:
Corinna Vinschen 2006-07-13 08:33:34 +00:00
parent d44b979536
commit f6105f89d5
4 changed files with 48 additions and 18 deletions

View File

@ -1,3 +1,14 @@
2006-07-13 Corinna Vinschen <corinna@vinschen.de>
* exceptions.cc (_cygtls::handle_exceptions): Call new
mmap_is_attached_or_noreserve_page function in case of access violation
and allow application to retry access on noreserve pages.
* mmap.cc (mmap_is_attached_or_noreserve_page): Changed from
mmap_is_attached_page. Handle also noreserve pages now. Change
comment accordingly.
* winsup.h (mmap_is_attached_or_noreserve_page): Declare instead of
mmap_is_attached_page.
2006-07-12 Corinna Vinschen <corinna@vinschen.de>
* mmap.cc (mmap_record::alloc_page_map): Don't call VirtualProtect

View File

@ -526,17 +526,21 @@ _cygtls::handle_exceptions (EXCEPTION_RECORD *e, exception_list *frame, CONTEXT
break;
case STATUS_ACCESS_VIOLATION:
if (mmap_is_attached_page (e->ExceptionInformation[1]))
{
switch (mmap_is_attached_or_noreserve_page (e->ExceptionInformation[1]))
{
case 2: /* MAP_NORESERVE page, now commited. */
return 0;
case 1: /* MAP_NORESERVE page, commit failed, or
access to mmap page beyond EOF. */
si.si_signo = SIGBUS;
si.si_code = BUS_OBJERR;
}
else
{
break;
default:
MEMORY_BASIC_INFORMATION m;
VirtualQuery ((PVOID) e->ExceptionInformation[1], &m, sizeof m);
si.si_signo = SIGSEGV;
si.si_code = m.State == MEM_FREE ? SEGV_MAPERR : SEGV_ACCERR;
break;
}
break;

View File

@ -900,13 +900,25 @@ map::del_list (unsigned i)
}
/* This function is called from exception_handler when a segmentation
violation has happened. The function should return true, if the
faulting address (the parameter) is within attached pages. In this
case the exception_handler raises SIGBUS, as demanded by the memory
protection extension described in SUSv3 (see the mmap man page).
If false is returned, a normal SIGSEGV is raised. */
bool
mmap_is_attached_page (ULONG_PTR addr)
violation has happened. We have two cases to check here.
First, is it an address within "attached" mmap pages (indicated by
the __PROT_ATTACH protection, see there)? In this case the function
returns 1 and the exception_handler raises SIGBUS, as demanded by the
memory protection extension described in SUSv3 (see the mmap man
page).
Second, check if the address is within "noreserve" mmap pages
(indicated by MAP_NORESERVE flag). If so, the function calls
VirtualAlloc to commit the page and returns 2. The exception handler
then just returns with 0 and the affected application retries the
failing memory access. If VirtualAlloc fails, the function returns
1, so that the exception handler raises a SIGBUS, as described in the
MAP_NORESERVE man pages for Linux and Solaris.
In any other case 0 is returned and a normal SIGSEGV is raised. */
int
mmap_is_attached_or_noreserve_page (ULONG_PTR addr)
{
list *map_list;
long record_idx;
@ -916,13 +928,16 @@ mmap_is_attached_page (ULONG_PTR addr)
addr = rounddown (addr, pagesize);
if (!(map_list = mmapped_areas.get_list_by_fd (-1)))
return false;
return 0;
if ((record_idx = map_list->search_record ((caddr_t)addr, pagesize,
u_addr, u_len, -1)) < 0)
return false;
if (!map_list->get_record (record_idx)->attached ())
return false;
return true;
return 0;
if (map_list->get_record (record_idx)->attached ())
return 1;
if (!map_list->get_record (record_idx)->noreserve ())
return 0;
DWORD new_prot = map_list->get_record (record_idx)->gen_protect ();
return VirtualAlloc ((void *)addr, pagesize, MEM_COMMIT, new_prot) ? 2 : 1;
}
static caddr_t

View File

@ -299,7 +299,7 @@ size_t getsystempagesize ();
/* mmap functions. */
void mmap_init ();
bool mmap_is_attached_page (ULONG_PTR);
int mmap_is_attached_or_noreserve_page (ULONG_PTR addr);
int winprio_to_nice (DWORD) __attribute__ ((regparm (1)));
DWORD nice_to_winprio (int &) __attribute__ ((regparm (1)));