Messages in this thread Patch in this message | | | Subject | PATCH: "gdb"" breakpoints (i.e., ptrace peeks/pokes) hang 2.1.37 | From | (Kevin Buhr) | Date | 15 May 1997 12:10:49 -0500 |
| |
Linus:
Between pre-patch-2.1.37-7 and 2.1.37, external calls to "do_no_page" and "do_wp_page" were changed to "handle_mm_fault" calls. However, in some cases the original "do_no_page" and "do_wp_page" calls took a "tsk" argument not equal to "current", and this fact is not communicated to "handle_mm_fault".
In particular, as reported to the list by a few others, using "gdb" breakpoints (e.g., "break main; run") hangs the 2.1.37 kernel, since the "ptrace" peeks and pokes end up trying to do "handle_mm_fault"s on behalf of the child process while the "current" process is the parent.
The enclosed patch against 2.1.37 defines a "handle_mm_fault_tsk" that takes an explicit "tsk" argument, redefines "handle_mm_fault" as an inline that calls "handle_mm_fault_tsk" with "tsk==current", and fixes the places in the kernel where "do_xx_page" became "handle_mm_fault" for "tsk!=current". (However, I only checked for changes between 2.1.pre37-7 and 2.1.37.)
A quick test shows that this fixes the hang-on-breakpoint bug mentioned above.
Kevin <buhr@stat.wisc.edu>
* * *
Index: linux/arch/i386/kernel/ptrace.c diff -u linux/arch/i386/kernel/ptrace.c:1.1.1.3 linux/arch/i386/kernel/ptrace.c:1.2 --- linux/arch/i386/kernel/ptrace.c:1.1.1.3 Wed May 14 10:00:41 1997 +++ linux/arch/i386/kernel/ptrace.c Thu May 15 12:32:11 1997 @@ -83,7 +83,7 @@ repeat: pgdir = pgd_offset(vma->vm_mm, addr); if (pgd_none(*pgdir)) { - handle_mm_fault(vma, addr, 0); + handle_mm_fault_tsk(tsk, vma, addr, 0); goto repeat; } if (pgd_bad(*pgdir)) { @@ -93,7 +93,7 @@ } pgmiddle = pmd_offset(pgdir, addr); if (pmd_none(*pgmiddle)) { - handle_mm_fault(vma, addr, 0); + handle_mm_fault_tsk(tsk, vma, addr, 0); goto repeat; } if (pmd_bad(*pgmiddle)) { @@ -103,7 +103,7 @@ } pgtable = pte_offset(pgmiddle, addr); if (!pte_present(*pgtable)) { - handle_mm_fault(vma, addr, 0); + handle_mm_fault_tsk(tsk, vma, addr, 0); goto repeat; } page = pte_page(*pgtable); @@ -134,7 +134,7 @@ repeat: pgdir = pgd_offset(vma->vm_mm, addr); if (!pgd_present(*pgdir)) { - handle_mm_fault(vma, addr, 1); + handle_mm_fault_tsk(tsk, vma, addr, 1); goto repeat; } if (pgd_bad(*pgdir)) { @@ -144,7 +144,7 @@ } pgmiddle = pmd_offset(pgdir, addr); if (pmd_none(*pgmiddle)) { - handle_mm_fault(vma, addr, 1); + handle_mm_fault_tsk(tsk, vma, addr, 1); goto repeat; } if (pmd_bad(*pgmiddle)) { @@ -154,12 +154,12 @@ } pgtable = pte_offset(pgmiddle, addr); if (!pte_present(*pgtable)) { - handle_mm_fault(vma, addr, 1); + handle_mm_fault_tsk(tsk, vma, addr, 1); goto repeat; } page = pte_page(*pgtable); if (!pte_write(*pgtable)) { - handle_mm_fault(vma, addr, 1); + handle_mm_fault_tsk(tsk, vma, addr, 1); goto repeat; } /* this is a hack for non-kernel-mapped video buffers and similar */ Index: linux/fs/proc/mem.c diff -u linux/fs/proc/mem.c:1.1.1.3 linux/fs/proc/mem.c:1.2 --- linux/fs/proc/mem.c:1.1.1.3 Wed May 14 09:58:07 1997 +++ linux/fs/proc/mem.c Thu May 15 12:32:14 1997 @@ -285,10 +285,10 @@ return -ENOMEM; if (!pte_present(*src_table)) - handle_mm_fault(src_vma, stmp, 1); + handle_mm_fault_tsk(tsk, src_vma, stmp, 1); if ((vma->vm_flags & VM_WRITE) && !pte_write(*src_table)) - handle_mm_fault(src_vma, stmp, 1); + handle_mm_fault_tsk(tsk, src_vma, stmp, 1); set_pte(src_table, pte_mkdirty(*src_table)); set_pte(dest_table, *src_table); Index: linux/include/linux/mm.h diff -u linux/include/linux/mm.h:1.1.1.3 linux/include/linux/mm.h:1.2 --- linux/include/linux/mm.h:1.1.1.3 Wed May 14 09:58:21 1997 +++ linux/include/linux/mm.h Thu May 15 12:32:15 1997 @@ -260,7 +260,8 @@ extern int zeromap_page_range(unsigned long from, unsigned long size, pgprot_t prot); extern void vmtruncate(struct inode * inode, unsigned long offset); -extern void handle_mm_fault(struct vm_area_struct *vma, unsigned long address, int write_access); +extern void handle_mm_fault_tsk(struct task_struct * tsk, struct vm_area_struct *vma, + unsigned long address, int write_access); extern unsigned long paging_init(unsigned long start_mem, unsigned long end_mem); extern void mem_init(unsigned long start_mem, unsigned long end_mem); @@ -268,7 +269,13 @@ extern void oom(struct task_struct * tsk); extern void si_meminfo(struct sysinfo * val); +extern inline void handle_mm_fault(struct vm_area_struct * vma, unsigned long address, + int write_access) +{ + handle_mm_fault_tsk(current, vma, address, write_access); +} + /* mmap.c */ extern void vma_init(void); extern unsigned long do_mmap(struct file * file, unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long off); Index: linux/mm/memory.c diff -u linux/mm/memory.c:1.1.1.2 linux/mm/memory.c:1.2 --- linux/mm/memory.c:1.1.1.2 Wed May 14 09:58:20 1997 +++ linux/mm/memory.c Thu May 15 12:32:16 1997 @@ -885,11 +885,11 @@ * with external mmu caches can use to update those (ie the Sparc or * PowerPC hashed page tables that act as extended TLBs). */ -static inline void handle_pte_fault(struct vm_area_struct * vma, unsigned long address, - int write_access, pte_t * pte) +static inline void handle_pte_fault(struct task_struct * tsk, struct vm_area_struct * vma, + unsigned long address, int write_access, pte_t * pte) { if (!pte_present(*pte)) { - do_no_page(current, vma, address, write_access); + do_no_page(tsk, vma, address, write_access); return; } set_pte(pte, pte_mkyoung(*pte)); @@ -901,11 +901,11 @@ flush_tlb_page(vma, address); return; } - do_wp_page(current, vma, address, write_access); + do_wp_page(tsk, vma, address, write_access); } -void handle_mm_fault(struct vm_area_struct * vma, unsigned long address, - int write_access) +void handle_mm_fault_tsk(struct task_struct * tsk, struct vm_area_struct * vma, + unsigned long address, int write_access) { pgd_t *pgd; pmd_t *pmd; @@ -918,9 +918,9 @@ pte = pte_alloc(pmd, address); if (!pte) goto no_memory; - handle_pte_fault(vma, address, write_access, pte); + handle_pte_fault(tsk, vma, address, write_access, pte); update_mmu_cache(vma, address, *pte); return; no_memory: - oom(current); + oom(tsk); }
| |