diff options
| author | Eli Zaretskii | 2016-02-14 19:46:29 +0200 |
|---|---|---|
| committer | Eli Zaretskii | 2016-02-14 19:46:29 +0200 |
| commit | 8badf953da5e629bc67db113719b72412270dabd (patch) | |
| tree | 4afa7a657a8f0308949e4f5555b26ebe23607283 /src/w32heap.c | |
| parent | 856cd948d1a5a016ad36721246a049d33451902f (diff) | |
| download | emacs-8badf953da5e629bc67db113719b72412270dabd.tar.gz emacs-8badf953da5e629bc67db113719b72412270dabd.zip | |
Make 'mmap_realloc' on MS-Windows more reliable
* src/w32heap.c (mmap_alloc): If reserving memory succeeds, but
committing fails, return NULL. Don't call GetLastError twice for
the same API error.
(mmap_realloc): Zero out MEMORY_BASIC_INFORMATION structures
before calling VirtualQuery, to avoid using garbled values if the
call fails. If committing more pages from the same block fails,
fall back on mmap_alloc + CopyMemory. Enhance debugging printouts
if the call to VirtualAlloc to commit more pages fails.
(Bug#22526)
Diffstat (limited to 'src/w32heap.c')
| -rw-r--r-- | src/w32heap.c | 51 |
1 files changed, 29 insertions, 22 deletions
diff --git a/src/w32heap.c b/src/w32heap.c index 00da86a9598..69706a3a57d 100644 --- a/src/w32heap.c +++ b/src/w32heap.c | |||
| @@ -652,15 +652,19 @@ mmap_alloc (void **var, size_t nbytes) | |||
| 652 | { | 652 | { |
| 653 | /* Now, commit pages for NBYTES. */ | 653 | /* Now, commit pages for NBYTES. */ |
| 654 | *var = VirtualAlloc (p, nbytes, MEM_COMMIT, PAGE_READWRITE); | 654 | *var = VirtualAlloc (p, nbytes, MEM_COMMIT, PAGE_READWRITE); |
| 655 | if (*var == NULL) | ||
| 656 | p = *var; | ||
| 655 | } | 657 | } |
| 656 | 658 | ||
| 657 | if (!p) | 659 | if (!p) |
| 658 | { | 660 | { |
| 659 | if (GetLastError () == ERROR_NOT_ENOUGH_MEMORY) | 661 | DWORD e = GetLastError (); |
| 662 | |||
| 663 | if (e == ERROR_NOT_ENOUGH_MEMORY) | ||
| 660 | errno = ENOMEM; | 664 | errno = ENOMEM; |
| 661 | else | 665 | else |
| 662 | { | 666 | { |
| 663 | DebPrint (("mmap_alloc: error %ld\n", GetLastError ())); | 667 | DebPrint (("mmap_alloc: error %ld\n", e)); |
| 664 | errno = EINVAL; | 668 | errno = EINVAL; |
| 665 | } | 669 | } |
| 666 | } | 670 | } |
| @@ -683,6 +687,7 @@ void * | |||
| 683 | mmap_realloc (void **var, size_t nbytes) | 687 | mmap_realloc (void **var, size_t nbytes) |
| 684 | { | 688 | { |
| 685 | MEMORY_BASIC_INFORMATION memInfo, m2; | 689 | MEMORY_BASIC_INFORMATION memInfo, m2; |
| 690 | void *old_ptr; | ||
| 686 | 691 | ||
| 687 | if (*var == NULL) | 692 | if (*var == NULL) |
| 688 | return mmap_alloc (var, nbytes); | 693 | return mmap_alloc (var, nbytes); |
| @@ -694,12 +699,14 @@ mmap_realloc (void **var, size_t nbytes) | |||
| 694 | return mmap_alloc (var, nbytes); | 699 | return mmap_alloc (var, nbytes); |
| 695 | } | 700 | } |
| 696 | 701 | ||
| 702 | memset (&memInfo, 0, sizeof (memInfo)); | ||
| 697 | if (VirtualQuery (*var, &memInfo, sizeof (memInfo)) == 0) | 703 | if (VirtualQuery (*var, &memInfo, sizeof (memInfo)) == 0) |
| 698 | DebPrint (("mmap_realloc: VirtualQuery error = %ld\n", GetLastError ())); | 704 | DebPrint (("mmap_realloc: VirtualQuery error = %ld\n", GetLastError ())); |
| 699 | 705 | ||
| 700 | /* We need to enlarge the block. */ | 706 | /* We need to enlarge the block. */ |
| 701 | if (memInfo.RegionSize < nbytes) | 707 | if (memInfo.RegionSize < nbytes) |
| 702 | { | 708 | { |
| 709 | memset (&m2, 0, sizeof (m2)); | ||
| 703 | if (VirtualQuery (*var + memInfo.RegionSize, &m2, sizeof(m2)) == 0) | 710 | if (VirtualQuery (*var + memInfo.RegionSize, &m2, sizeof(m2)) == 0) |
| 704 | DebPrint (("mmap_realloc: VirtualQuery error = %ld\n", | 711 | DebPrint (("mmap_realloc: VirtualQuery error = %ld\n", |
| 705 | GetLastError ())); | 712 | GetLastError ())); |
| @@ -715,31 +722,31 @@ mmap_realloc (void **var, size_t nbytes) | |||
| 715 | MEM_COMMIT, PAGE_READWRITE); | 722 | MEM_COMMIT, PAGE_READWRITE); |
| 716 | if (!p /* && GetLastError() != ERROR_NOT_ENOUGH_MEMORY */) | 723 | if (!p /* && GetLastError() != ERROR_NOT_ENOUGH_MEMORY */) |
| 717 | { | 724 | { |
| 718 | DebPrint (("realloc enlarge: VirtualAlloc error %ld\n", | 725 | DebPrint (("realloc enlarge: VirtualAlloc (%p + %I64x, %I64x) error %ld\n", |
| 726 | *var, (uint64_t)memInfo.RegionSize, | ||
| 727 | (uint64_t)(nbytes - memInfo.RegionSize), | ||
| 719 | GetLastError ())); | 728 | GetLastError ())); |
| 720 | errno = ENOMEM; | 729 | DebPrint (("next region: %p %p %I64x %x\n", m2.BaseAddress, |
| 730 | m2.AllocationBase, m2.RegionSize, m2.AllocationProtect)); | ||
| 721 | } | 731 | } |
| 732 | else | ||
| 733 | return *var; | ||
| 734 | } | ||
| 735 | /* Else we must actually enlarge the block by allocating a new | ||
| 736 | one and copying previous contents from the old to the new one. */ | ||
| 737 | old_ptr = *var; | ||
| 738 | |||
| 739 | if (mmap_alloc (var, nbytes)) | ||
| 740 | { | ||
| 741 | CopyMemory (*var, old_ptr, memInfo.RegionSize); | ||
| 742 | mmap_free (&old_ptr); | ||
| 722 | return *var; | 743 | return *var; |
| 723 | } | 744 | } |
| 724 | else | 745 | else |
| 725 | { | 746 | { |
| 726 | /* Else we must actually enlarge the block by allocating a | 747 | /* We failed to reallocate the buffer. */ |
| 727 | new one and copying previous contents from the old to the | 748 | *var = old_ptr; |
| 728 | new one. */ | 749 | return NULL; |
| 729 | void *old_ptr = *var; | ||
| 730 | |||
| 731 | if (mmap_alloc (var, nbytes)) | ||
| 732 | { | ||
| 733 | CopyMemory (*var, old_ptr, memInfo.RegionSize); | ||
| 734 | mmap_free (&old_ptr); | ||
| 735 | return *var; | ||
| 736 | } | ||
| 737 | else | ||
| 738 | { | ||
| 739 | /* We failed to enlarge the buffer. */ | ||
| 740 | *var = old_ptr; | ||
| 741 | return NULL; | ||
| 742 | } | ||
| 743 | } | 750 | } |
| 744 | } | 751 | } |
| 745 | 752 | ||
| @@ -751,7 +758,7 @@ mmap_realloc (void **var, size_t nbytes) | |||
| 751 | { | 758 | { |
| 752 | /* Let's give some memory back to the system and release | 759 | /* Let's give some memory back to the system and release |
| 753 | some pages. */ | 760 | some pages. */ |
| 754 | void *old_ptr = *var; | 761 | old_ptr = *var; |
| 755 | 762 | ||
| 756 | if (mmap_alloc (var, nbytes)) | 763 | if (mmap_alloc (var, nbytes)) |
| 757 | { | 764 | { |