aboutsummaryrefslogtreecommitdiffstats
path: root/src/w32heap.c
diff options
context:
space:
mode:
authorEli Zaretskii2016-02-14 19:46:29 +0200
committerEli Zaretskii2016-02-14 19:46:29 +0200
commit8badf953da5e629bc67db113719b72412270dabd (patch)
tree4afa7a657a8f0308949e4f5555b26ebe23607283 /src/w32heap.c
parent856cd948d1a5a016ad36721246a049d33451902f (diff)
downloademacs-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.c51
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 *
683mmap_realloc (void **var, size_t nbytes) 687mmap_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 {