From owner-freebsd-www@FreeBSD.ORG Mon May 25 11:07:04 2009 Return-Path: Delivered-To: freebsd-www@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 3016010656AC for ; Mon, 25 May 2009 11:07:04 +0000 (UTC) (envelope-from owner-bugmaster@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:4f8:fff6::28]) by mx1.freebsd.org (Postfix) with ESMTP id 65CDD8FC0A for ; Mon, 25 May 2009 11:07:03 +0000 (UTC) (envelope-from owner-bugmaster@FreeBSD.org) Received: from freefall.freebsd.org (localhost [127.0.0.1]) by freefall.freebsd.org (8.14.3/8.14.3) with ESMTP id n4PB73LM093007 for ; Mon, 25 May 2009 11:07:03 GMT (envelope-from owner-bugmaster@FreeBSD.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.3/8.14.3/Submit) id n4PB72FI093003 for freebsd-www@FreeBSD.org; Mon, 25 May 2009 11:07:02 GMT (envelope-from owner-bugmaster@FreeBSD.org) Date: Mon, 25 May 2009 11:07:02 GMT Message-Id: <200905251107.n4PB72FI093003@freefall.freebsd.org> X-Authentication-Warning: freefall.freebsd.org: gnats set sender to owner-bugmaster@FreeBSD.org using -f From: FreeBSD bugmaster To: freebsd-www@FreeBSD.org Cc: Subject: Current problem reports assigned to freebsd-www@FreeBSD.org X-BeenThere: freebsd-www@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: FreeBSD Project Webmasters List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 25 May 2009 11:07:06 -0000 Note: to view an individual PR, use: http://www.freebsd.org/cgi/query-pr.cgi?pr=(number). The following is a listing of current problems submitted by FreeBSD users. These represent problem reports covering all versions including experimental development code and obsolete releases. S Tracker Resp. Description -------------------------------------------------------------------------------- o www/134505 www www.freebsd.org does not correctly process If-Modified o www/133862 www 24 bit version of FreeBSD favicon o www/133730 www amd64 motherboard success report: Asrock A770DE AMD7 o www/133262 www FreeBSD on ASUS M2N-MX SE + f www/132178 www Soekris not listed amoung hardware vendors o www/132149 www Problem with submitting emails to freebsd-questions@fr o www/132091 www russian freebsd copyright - wrong translation f www/131863 www Please add to Commercial Vendors listing o www/131493 www sshd(8) and sshd_config(8) on-line man pages outdated o www/130627 www Submission for www/en/platforms/amd64/motherboards.sgm f www/130340 www Submission for ISP page o www/129969 www Need 301 moved permanently errors returned for www.fre o www/129923 www Need stylesheet for FreeBSD Subversion DAV tree o www/129622 www amd64 motherboard - new board to add to the supported o www/129401 www FreeBSD Multimedia page should automatically pick up Y o www/129331 www Supported motherboard Gigabyte GA-MA78GPM-DS2H o www/128943 www dmesg output for ASUS M3A79-T running FreeBSD-7.1-PRER o www/128113 www outdated port count graph in www.freebsd.org/ports o www/127497 www new entry to FreeBSD/amd64 Project -- motherboards f www/121391 www Please add us on the ISP pages... o www/116660 www docs.freebsd.org returns bad chunked encoding o www/116479 www cvsweb+enscript formatting bugfix s www/111791 www FreeBSD website messes up while using "links" browser o www/105333 www [patch] Base selection in events in libcommon.xsl does o www/103522 www Search interface oddity o www/98798 www Our statistics page is out of date o www/91539 www FreeBSD web site renders very badly s www/73551 www [request] fix list archive 'quoted-printable' corrupti o www/51135 www Problems with the mailing-lists search interface o www/44181 www www "Release Information" organization 30 problems total. From owner-freebsd-www@FreeBSD.ORG Tue May 26 12:50:01 2009 Return-Path: Delivered-To: freebsd-www@hub.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 8BF1F1065674 for ; Tue, 26 May 2009 12:50:01 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:4f8:fff6::28]) by mx1.freebsd.org (Postfix) with ESMTP id 6608A8FC16 for ; Tue, 26 May 2009 12:50:01 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.14.3/8.14.3) with ESMTP id n4QCo1FB063594 for ; Tue, 26 May 2009 12:50:01 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.3/8.14.3/Submit) id n4QCo1hk063593; Tue, 26 May 2009 12:50:01 GMT (envelope-from gnats) Resent-Date: Tue, 26 May 2009 12:50:01 GMT Resent-Message-Id: <200905261250.n4QCo1hk063593@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-www@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, alexander lunyov Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 2AE031065678 for ; Tue, 26 May 2009 12:41:15 +0000 (UTC) (envelope-from nobody@FreeBSD.org) Received: from www.freebsd.org (www.freebsd.org [IPv6:2001:4f8:fff6::21]) by mx1.freebsd.org (Postfix) with ESMTP id 1725E8FC27 for ; Tue, 26 May 2009 12:41:15 +0000 (UTC) (envelope-from nobody@FreeBSD.org) Received: from www.freebsd.org (localhost [127.0.0.1]) by www.freebsd.org (8.14.3/8.14.3) with ESMTP id n4QCfEMD026142 for ; Tue, 26 May 2009 12:41:15 GMT (envelope-from nobody@www.freebsd.org) Received: (from nobody@localhost) by www.freebsd.org (8.14.3/8.14.3/Submit) id n4QCfEpw026141; Tue, 26 May 2009 12:41:14 GMT (envelope-from nobody) Message-Id: <200905261241.n4QCfEpw026141@www.freebsd.org> Date: Tue, 26 May 2009 12:41:14 GMT From: alexander lunyov To: freebsd-gnats-submit@FreeBSD.org X-Send-Pr-Version: www-3.1 Cc: Subject: www/134958: Motherboard support report for amd64 project X-BeenThere: freebsd-www@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: FreeBSD Project Webmasters List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 26 May 2009 12:50:02 -0000 >Number: 134958 >Category: www >Synopsis: Motherboard support report for amd64 project >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-www >State: open >Quarter: >Keywords: >Date-Required: >Class: change-request >Submitter-Id: current-users >Arrival-Date: Tue May 26 12:50:01 UTC 2009 >Closed-Date: >Last-Modified: >Originator: alexander lunyov >Release: 7.2-RELEASE >Organization: OAO RTK >Environment: FreeBSD mail.zato.ru 7.2-RELEASE FreeBSD 7.2-RELEASE #1: Mon May 4 11:37:29 MSD 2009 root@mail2.zato.ru:/usr/obj/usr/src/sys/mail2_amd64 amd64 >Description: It's a motherboard support report for project amd64. We have Supermicro 6025B-TR+B server with motherboard X7DBE+, http://www.supermicro.com/products/motherboard/Xeon1333/5000P/X7DBE+.cfm. It is a mail server with ZFS RAIDZ storage pool of 5 SATA disks (1 SATA is boot disk and not in pool). For now only network peripherals has been tested, and everything is working fine. Dmesg: # cat /var/run/dmesg.boot Copyright (c) 1992-2009 The FreeBSD Project. Copyright (c) 1979, 1980, 1983, 1986, 1988, 1989, 1991, 1992, 1993, 1994 The Regents of the University of California. All rights reserved. FreeBSD is a registered trademark of The FreeBSD Foundation. FreeBSD 7.2-RELEASE #1: Mon May 4 11:37:29 MSD 2009 root@mail2.zato.ru:/usr/obj/usr/src/sys/mail2_amd64 Timecounter "i8254" frequency 1193182 Hz quality 0 CPU: Intel(R) Xeon(R) CPU E5205 @ 1.86GHz (1866.74-MHz K8-class CPU) Origin = "GenuineIntel" Id = 0x10676 Stepping = 6 Features=0xbfebfbff Features2=0xce3bd> AMD Features=0x20100800 AMD Features2=0x1 Cores per package: 2 usable memory = 4283822080 (4085 MB) avail memory = 4110827520 (3920 MB) ACPI APIC Table: FreeBSD/SMP: Multiprocessor System Detected: 4 CPUs cpu0 (BSP): APIC ID: 0 cpu1 (AP): APIC ID: 1 cpu2 (AP): APIC ID: 6 cpu3 (AP): APIC ID: 7 ioapic0 irqs 0-23 on motherboard ioapic1 irqs 24-47 on motherboard kbd1 at kbdmux0 acpi0: on motherboard acpi0: [ITHREAD] acpi0: Power Button (fixed) Timecounter "ACPI-fast" frequency 3579545 Hz quality 1000 acpi_timer0: <24-bit timer at 3.579545MHz> port 0x1008-0x100b on acpi0 pcib0: port 0xcf8-0xcff on acpi0 pci0: on pcib0 pcib1: at device 2.0 on pci0 pci1: on pcib1 pcib2: irq 16 at device 0.0 on pci1 pci2: on pcib2 pcib3: irq 16 at device 0.0 on pci2 pci3: on pcib3 pcib4: at device 0.0 on pci3 pci4: on pcib4 pcib5: at device 0.2 on pci3 pci5: on pcib5 pcib6: irq 18 at device 2.0 on pci2 pci6: on pcib6 em0: port 0x2000-0x201f mem 0xd8020000-0xd803ffff,0xd8000000-0xd801ffff irq 18 at device 0.0 on pci6 em0: Using MSI interrupt em0: [FILTER] em0: Ethernet address: 00:30:48:c1:e1:b4 em1: port 0x2020-0x203f mem 0xd8060000-0xd807ffff,0xd8040000-0xd805ffff irq 19 at device 0.1 on pci6 em1: Using MSI interrupt em1: [FILTER] em1: Ethernet address: 00:30:48:c1:e1:b5 pcib7: at device 0.3 on pci1 pci7: on pcib7 pcib8: at device 4.0 on pci0 pci8: on pcib8 pcib9: at device 6.0 on pci0 pci9: on pcib9 pci0: at device 8.0 (no driver attached) pcib10: irq 17 at device 28.0 on pci0 pci10: on pcib10 uhci0: port 0x1800-0x181f irq 17 at device 29.0 on pci0 uhci0: [GIANT-LOCKED] uhci0: [ITHREAD] usb0: on uhci0 usb0: USB revision 1.0 uhub0: on usb0 uhub0: 2 ports with 2 removable, self powered uhci1: port 0x1820-0x183f irq 19 at device 29.1 on pci0 uhci1: [GIANT-LOCKED] uhci1: [ITHREAD] usb1: on uhci1 usb1: USB revision 1.0 uhub1: on usb1 uhub1: 2 ports with 2 removable, self powered uhci2: port 0x1840-0x185f irq 18 at device 29.2 on pci0 uhci2: [GIANT-LOCKED] uhci2: [ITHREAD] usb2: on uhci2 usb2: USB revision 1.0 uhub2: on usb2 uhub2: 2 ports with 2 removable, self powered ehci0: mem 0xd8500000-0xd85003ff irq 17 at device 29.7 on pci0 ehci0: [GIANT-LOCKED] ehci0: [ITHREAD] usb3: EHCI version 1.0 usb3: companion controllers, 2 ports each: usb0 usb1 usb2 usb3: on ehci0 usb3: USB revision 2.0 uhub3: on usb3 uhub3: 6 ports with 6 removable, self powered pcib11: at device 30.0 on pci0 pci11: on pcib11 vgapci0: port 0x3000-0x30ff mem 0xd0000000-0xd7ffffff,0xd8200000-0xd820ffff irq 18 at device 1.0 on pci11 isab0: at device 31.0 on pci0 isa0: on isab0 atapci0: port 0x1f0-0x1f7,0x3f6,0x170-0x177,0x376,0x1860-0x186f at device 31.1 on pci0 ata0: on atapci0 ata0: [ITHREAD] atapci1: port 0x18a0-0x18a7,0x1874-0x1877,0x1878-0x187f,0x1870-0x1873,0x1880-0x189f mem 0xd8500400-0xd85007ff irq 19 at device 31.2 on pci0 atapci1: [ITHREAD] atapci1: AHCI called from vendor specific driver atapci1: AHCI Version 01.10 controller with 6 ports detected ata2: on atapci1 ata2: [ITHREAD] ata3: on atapci1 ata3: [ITHREAD] ata4: on atapci1 ata4: [ITHREAD] ata5: on atapci1 ata5: [ITHREAD] ata6: on atapci1 ata6: [ITHREAD] ata7: on atapci1 ata7: [ITHREAD] pci0: at device 31.3 (no driver attached) acpi_button0: on acpi0 atkbdc0: port 0x60,0x64 irq 1 on acpi0 atkbd0: irq 1 on atkbdc0 kbd0 at atkbd0 atkbd0: [GIANT-LOCKED] atkbd0: [ITHREAD] sio0: configured irq 4 not in bitmap of probed irqs 0 sio0: port may not be enabled sio0: configured irq 4 not in bitmap of probed irqs 0 sio0: port may not be enabled sio0: <16550A-compatible COM port> port 0x3f8-0x3ff irq 4 flags 0x10 on acpi0 sio0: type 16550A sio0: [FILTER] sio1: configured irq 3 not in bitmap of probed irqs 0 sio1: port may not be enabled sio1: configured irq 3 not in bitmap of probed irqs 0 sio1: port may not be enabled sio1: <16550A-compatible COM port> port 0x2f8-0x2ff irq 3 on acpi0 sio1: type 16550A sio1: [FILTER] fdc0: port 0x3f0-0x3f5,0x3f7 irq 6 drq 2 on acpi0 fdc0: [FILTER] ppc0: port 0x378-0x37f,0x778-0x77f irq 7 drq 3 on acpi0 ppc0: SMC-like chipset (ECP/EPP/PS2/NIBBLE) in COMPATIBLE mode ppc0: FIFO with 16/16/9 bytes threshold ppbus0: on ppc0 ppbus0: [ITHREAD] plip0: on ppbus0 plip0: WARNING: using obsoleted IFF_NEEDSGIANT flag lpt0: on ppbus0 lpt0: Interrupt-driven port ppi0: on ppbus0 ppc0: [GIANT-LOCKED] ppc0: [ITHREAD] cpu0: on acpi0 est0: on cpu0 est: CPU supports Enhanced Speedstep, but is not recognized. est: cpu_vendor GenuineIntel, msr 720072006000720 device_attach: est0 attach returned 6 p4tcc0: on cpu0 cpu1: on acpi0 est1: on cpu1 est: CPU supports Enhanced Speedstep, but is not recognized. est: cpu_vendor GenuineIntel, msr 720072006000720 device_attach: est1 attach returned 6 p4tcc1: on cpu1 cpu2: on acpi0 est2: on cpu2 est: CPU supports Enhanced Speedstep, but is not recognized. est: cpu_vendor GenuineIntel, msr 720072006000720 device_attach: est2 attach returned 6 p4tcc2: on cpu2 cpu3: on acpi0 est3: on cpu3 est: CPU supports Enhanced Speedstep, but is not recognized. est: cpu_vendor GenuineIntel, msr 720072006000720 device_attach: est3 attach returned 6 p4tcc3: on cpu3 orm0: at iomem 0xc0000-0xcafff,0xcb000-0xd07ff on isa0 sc0: at flags 0x100 on isa0 sc0: VGA <16 virtual consoles, flags=0x300> vga0: at port 0x3c0-0x3df iomem 0xa0000-0xbffff on isa0 Timecounters tick every 1.000 msec ipfw2 (+ipv6) initialized, divert enabled, nat loadable, rule-based forwarding enabled, default to deny, logging disabled acd0: DMA limited to UDMA33, controller found non-ATA66 cable acd0: DVDROM at ata0-slave UDMA33 ad4: 476940MB at ata2-master SATA150 ad6: 476940MB at ata3-master SATA150 ad8: 476940MB at ata4-master SATA150 ad10: 476940MB at ata5-master SATA150 ad12: 476940MB at ata6-master SATA150 GEOM_LABEL: Label for provider ad4s1a is ufsid/4981d8d2a59197c4. ad14: 476940MB at ata7-master SATA150 GEOM_LABEL: Label for provider ad4s1d is ufsid/4981d8d4de653cac. SMP: AP CPU #1 Launched! SMP: AP CPU #2 Launched! SMP: AP CPU #3 Launched! GEOM_LABEL: Label for provider ad4s1e is ufsid/4981d8d2af584b06. Trying to mount root from ufs:/dev/ad4s1a GEOM_LABEL: Label ufsid/4981d8d2a59197c4 removed. GEOM_LABEL: Label for provider ad4s1a is ufsid/4981d8d2a59197c4. GEOM_LABEL: Label ufsid/4981d8d2af584b06 removed. GEOM_LABEL: Label for provider ad4s1e is ufsid/4981d8d2af584b06. GEOM_LABEL: Label ufsid/4981d8d4de653cac removed. GEOM_LABEL: Label for provider ad4s1d is ufsid/4981d8d4de653cac. GEOM_LABEL: Label ufsid/4981d8d2a59197c4 removed. GEOM_LABEL: Label ufsid/4981d8d2af584b06 removed. GEOM_LABEL: Label ufsid/4981d8d4de653cac removed. This module (opensolaris) contains code covered by the Common Development and Distribution License (CDDL) see http://opensolaris.org/os/licensing/opensolaris_license/ WARNING: ZFS is considered to be an experimental feature in FreeBSD. ZFS filesystem version 6 ZFS storage pool version 6 pciconf: # pciconf -lv hostb0@pci0:0:0:0: class=0x060000 card=0x808015d9 chip=0x25d88086 rev=0xb1 hdr=0x00 vendor = 'Intel Corporation' device = '5000P Chipset Memory Controller Hub' class = bridge subclass = HOST-PCI pcib1@pci0:0:2:0: class=0x060400 card=0x00000000 chip=0x25f78086 rev=0xb1 hdr=0x01 vendor = 'Intel Corporation' device = '5000 Series Chipset PCIe x8 Port 2-3' class = bridge subclass = PCI-PCI pcib8@pci0:0:4:0: class=0x060400 card=0x00000000 chip=0x25f88086 rev=0xb1 hdr=0x01 vendor = 'Intel Corporation' device = '5000 Series Chipset PCIe x8 Port 4-5' class = bridge subclass = PCI-PCI pcib9@pci0:0:6:0: class=0x060400 card=0x00000000 chip=0x25f98086 rev=0xb1 hdr=0x01 vendor = 'Intel Corporation' device = '5000 Series Chipset PCIe x8 Port 6-7' class = bridge subclass = PCI-PCI none0@pci0:0:8:0: class=0x088000 card=0x808015d9 chip=0x1a388086 rev=0xb1 hdr=0x00 vendor = 'Intel Corporation' device = '5000 5000 Series Chipset DMA Engine' class = base peripheral hostb1@pci0:0:16:0: class=0x060000 card=0x808015d9 chip=0x25f08086 rev=0xb1 hdr=0x00 vendor = 'Intel Corporation' device = '5000 Series Chipset Error Reporting Registers' class = bridge subclass = HOST-PCI hostb2@pci0:0:16:1: class=0x060000 card=0x808015d9 chip=0x25f08086 rev=0xb1 hdr=0x00 vendor = 'Intel Corporation' device = '5000 Series Chipset Error Reporting Registers' class = bridge subclass = HOST-PCI hostb3@pci0:0:16:2: class=0x060000 card=0x808015d9 chip=0x25f08086 rev=0xb1 hdr=0x00 vendor = 'Intel Corporation' device = '5000 Series Chipset Error Reporting Registers' class = bridge subclass = HOST-PCI hostb4@pci0:0:17:0: class=0x060000 card=0x808015d9 chip=0x25f18086 rev=0xb1 hdr=0x00 vendor = 'Intel Corporation' device = '5000 Series Chipset Reserved Registers' class = bridge subclass = HOST-PCI hostb5@pci0:0:19:0: class=0x060000 card=0x808015d9 chip=0x25f38086 rev=0xb1 hdr=0x00 vendor = 'Intel Corporation' device = '5000 Series Chipset Reserved Registers' class = bridge subclass = HOST-PCI hostb6@pci0:0:21:0: class=0x060000 card=0x808015d9 chip=0x25f58086 rev=0xb1 hdr=0x00 vendor = 'Intel Corporation' device = '5000 Series Chipset FBD Registers' class = bridge subclass = HOST-PCI hostb7@pci0:0:22:0: class=0x060000 card=0x808015d9 chip=0x25f68086 rev=0xb1 hdr=0x00 vendor = 'Intel Corporation' device = '5000 Series Chipset FBD Registers' class = bridge subclass = HOST-PCI pcib10@pci0:0:28:0: class=0x060400 card=0x808015d9 chip=0x26908086 rev=0x09 hdr=0x01 vendor = 'Intel Corporation' device = '631xESB/632xESB/3100 PCIe Root Port 1' class = bridge subclass = PCI-PCI uhci0@pci0:0:29:0: class=0x0c0300 card=0x808015d9 chip=0x26888086 rev=0x09 hdr=0x00 vendor = 'Intel Corporation' device = '631xESB/632xESB/3100 Chipset USB Universal Host Controller' class = serial bus subclass = USB uhci1@pci0:0:29:1: class=0x0c0300 card=0x808015d9 chip=0x26898086 rev=0x09 hdr=0x00 vendor = 'Intel Corporation' device = '631xESB/632xESB/3100 Chipset USB Universal Host Controller' class = serial bus subclass = USB uhci2@pci0:0:29:2: class=0x0c0300 card=0x808015d9 chip=0x268a8086 rev=0x09 hdr=0x00 vendor = 'Intel Corporation' device = '631xESB/632xESB/3100 Chipset USB Universal Host Controller' class = serial bus subclass = USB ehci0@pci0:0:29:7: class=0x0c0320 card=0x808015d9 chip=0x268c8086 rev=0x09 hdr=0x00 vendor = 'Intel Corporation' device = '631xESB/632xESB/3100 Chipset USB2 Enhanced Host Controller' class = serial bus subclass = USB pcib11@pci0:0:30:0: class=0x060401 card=0x808015d9 chip=0x244e8086 rev=0xd9 hdr=0x01 vendor = 'Intel Corporation' device = '82801 Family (ICH2/3/4/4/5/5/6/7/8/9,63xxESB) Hub Interface to PCI Bridge' class = bridge subclass = PCI-PCI isab0@pci0:0:31:0: class=0x060100 card=0x808015d9 chip=0x26708086 rev=0x09 hdr=0x00 vendor = 'Intel Corporation' device = '631xESB/632xESB/3100 LPC Interface Controller' class = bridge subclass = PCI-ISA atapci0@pci0:0:31:1: class=0x01018a card=0x808015d9 chip=0x269e8086 rev=0x09 hdr=0x00 vendor = 'Intel Corporation' device = '631xESB/632xESB/3100 Ultra ATA Storage Controller' class = mass storage subclass = ATA atapci1@pci0:0:31:2: class=0x010400 card=0x808015d9 chip=0x26828086 rev=0x09 hdr=0x00 vendor = 'Intel Corporation' device = 'Enterprise Southbridge SATA cc=RAID' class = mass storage subclass = RAID none1@pci0:0:31:3: class=0x0c0500 card=0x808015d9 chip=0x269b8086 rev=0x09 hdr=0x00 vendor = 'Intel Corporation' device = '631xESB/632xESB/3100 SMBus Controller' class = serial bus subclass = SMBus pcib2@pci0:1:0:0: class=0x060400 card=0x808015d9 chip=0x35008086 rev=0x01 hdr=0x01 vendor = 'Intel Corporation' device = '631xESB/632xESB PCIe Upstream Port' class = bridge subclass = PCI-PCI pcib7@pci0:1:0:3: class=0x060400 card=0x808015d9 chip=0x350c8086 rev=0x01 hdr=0x01 vendor = 'Intel Corporation' device = '631xESB/632xESB PCIe to PCI-X Bridge' class = bridge subclass = PCI-PCI pcib3@pci0:2:0:0: class=0x060400 card=0x808015d9 chip=0x35108086 rev=0x01 hdr=0x01 vendor = 'Intel Corporation' device = '631xESB/632xESB PCIe Downstream Port E1' class = bridge subclass = PCI-PCI pcib6@pci0:2:2:0: class=0x060400 card=0x808015d9 chip=0x35188086 rev=0x01 hdr=0x01 vendor = 'Intel Corporation' device = '631xESB/632xESB PCIe Downstream Port E3' class = bridge subclass = PCI-PCI pcib4@pci0:3:0:0: class=0x060400 card=0x00000000 chip=0x03298086 rev=0x09 hdr=0x01 vendor = 'Intel Corporation' device = '6700PXH PCI Express-to-PCI Express Bridge A' class = bridge subclass = PCI-PCI pcib5@pci0:3:0:2: class=0x060400 card=0x00000000 chip=0x032a8086 rev=0x09 hdr=0x01 vendor = 'Intel Corporation' device = '6700PXH PCI Express-to-PCI Express Bridge B' class = bridge subclass = PCI-PCI em0@pci0:6:0:0: class=0x020000 card=0x109615d9 chip=0x10968086 rev=0x01 hdr=0x00 vendor = 'Intel Corporation' device = 'PRO/1000 EB Network Connection' class = network subclass = ethernet em1@pci0:6:0:1: class=0x020000 card=0x109615d9 chip=0x10968086 rev=0x01 hdr=0x00 vendor = 'Intel Corporation' device = 'PRO/1000 EB Network Connection' class = network subclass = ethernet vgapci0@pci0:11:1:0: class=0x030000 card=0x808015d9 chip=0x515e1002 rev=0x02 hdr=0x00 vendor = 'ATI Technologies Inc' device = 'Radeon ES1000 Radeon ES1000' class = display subclass = VGA >How-To-Repeat: >Fix: >Release-Note: >Audit-Trail: >Unformatted: From owner-freebsd-www@FreeBSD.ORG Fri May 29 19:16:07 2009 Return-Path: Delivered-To: www@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 190E2106566B for ; Fri, 29 May 2009 19:16:07 +0000 (UTC) (envelope-from jgreen.mac@gmail.com) Received: from mail-gx0-f218.google.com (mail-gx0-f218.google.com [209.85.217.218]) by mx1.freebsd.org (Postfix) with ESMTP id C2B828FC1D for ; Fri, 29 May 2009 19:16:06 +0000 (UTC) (envelope-from jgreen.mac@gmail.com) Received: by gxk18 with SMTP id 18so1440477gxk.19 for ; Fri, 29 May 2009 12:16:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:mime-version:received:date:message-id:subject :from:to:content-type:content-transfer-encoding; bh=lnxS31PdpSaqIhQ2d28x56hUf/oWQD3n0QMkZUCuXZA=; b=CwUdCW2UGuLlr7YriyJLaSL00wf5STn+gHSe7Ye6I0uUxTQZLXfVdt/XZcFIfImaq6 P8HgkyueA8gqLHj/zuSW/hr9RlyKdhHFz8EN6H3nC5j7ofdLnXVJmO6zVhzNWNbS8edq aeaHPJdVSHszgIYOu01SJ+sHDspHQl5IgBcxQ= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=mime-version:date:message-id:subject:from:to:content-type :content-transfer-encoding; b=vPkfyBWVB4HfeERHiaiWd2pxJtMVOY6r6ytnd3wmsBjW1B4zBmD9JboqjbLxpfTwF2 xcx8L882pKDQRGpLfilzCU3QKwJ6wYit+6/pktIXEeZvSYFHljiAiawSFWJQ+2UGtx0D bsGk6Fs4qf/Qv1lGpJFNmDTOoufPgtXaXjR5U= MIME-Version: 1.0 Received: by 10.150.11.20 with SMTP id 20mr5666679ybk.280.1243624565373; Fri, 29 May 2009 12:16:05 -0700 (PDT) Date: Fri, 29 May 2009 12:16:05 -0700 Message-ID: From: Joshua Green To: www@freebsd.org Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit Cc: Subject: China chooses FreeBSD as basis for secure OS X-BeenThere: freebsd-www@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: FreeBSD Project Webmasters List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 29 May 2009 19:16:07 -0000 http://blogs.techrepublic.com.com/security/?p=1682 From owner-freebsd-www@FreeBSD.ORG Sat May 30 02:08:20 2009 Return-Path: Delivered-To: www@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 857FD1065670 for ; Sat, 30 May 2009 02:08:20 +0000 (UTC) (envelope-from steve.marks@campaign.raywhite.com) Received: from mx-1.tlcollect.com (mx-1.tlcollect.com [210.193.131.133]) by mx1.freebsd.org (Postfix) with ESMTP id 1AE908FC18 for ; Sat, 30 May 2009 02:08:19 +0000 (UTC) (envelope-from steve.marks@campaign.raywhite.com) Received: from mail pickup service by mx-1.tlcollect.com with Microsoft SMTPSVC; Fri, 29 May 2009 20:45:59 -0400 Thread-Topic: Bank Sale falls over X-Habeas-Report: Please report use of this mark in spam to X-Campaign: TL-ZZ83KJ85u69t27Pt58z Errors-To: Accreditor: Habeas thread-index: AcngwAAWMrMgy0/kS6ykmEfOD2SXTg== From: "Steve Marks" Sender: To: Date: Fri, 29 May 2009 20:45:59 -0400 Message-ID: <09AAF0A964314A4BB68C5B420C22627A@mailserver1> MIME-Version: 1.0 X-Mailer: Microsoft CDO for Windows 2000 Content-Class: urn:content-classes:message Importance: normal Priority: normal X-MimeOLE: Produced By Microsoft MimeOLE V6.00.3790.4325 X-OriginalArrivalTime: 30 May 2009 00:45:59.0875 (UTC) FILETIME=[00378130:01C9E0C0] Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Content-Filtered-By: Mailman/MimeDel 2.1.5 Cc: Subject: Bank Sale falls over X-BeenThere: freebsd-www@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: TL-ZZ83KJ85u69t27Pt58z@campaign.raywhite.com List-Id: FreeBSD Project Webmasters List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 30 May 2009 02:08:20 -0000 Dear , You have just received a message from Steve Marks at Ray White = Whitsunday. To view your message, please visit the following address: http://campaign.raywhite.com/ve/ZZ83KJ85u69t27Pt58z To unsubscribe, reply to this email and change the subject to be: = unsubscribe If you have trouble viewing this message please see below for detailed = instructions. ________________________________________ If your e-mail program does not allow you to click directly on the above = address (such as AOL), you will need to copy and paste the address into = your World Wide Web browser (eg Netscape Navigator or Internet = Explorer). Follow the directions below for the simplest way to pick up your = message. 1. Make sure you only have one web browser open. 2. Highlight the address by dragging the cursor across the URL (make = sure you get the whole address). 3. Copy and paste the URL into your web browser. 4. Press 'enter'. From owner-freebsd-www@FreeBSD.ORG Sat May 30 15:10:03 2009 Return-Path: Delivered-To: freebsd-www@hub.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 85A141065673 for ; Sat, 30 May 2009 15:10:03 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:4f8:fff6::28]) by mx1.freebsd.org (Postfix) with ESMTP id 603B58FC15 for ; Sat, 30 May 2009 15:10:03 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.14.3/8.14.3) with ESMTP id n4UFA3ga016167 for ; Sat, 30 May 2009 15:10:03 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.3/8.14.3/Submit) id n4UFA3Jd016166; Sat, 30 May 2009 15:10:03 GMT (envelope-from gnats) Resent-Date: Sat, 30 May 2009 15:10:03 GMT Resent-Message-Id: <200905301510.n4UFA3Jd016166@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-www@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, Jille Timmermans Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 45B831065673 for ; Sat, 30 May 2009 15:03:40 +0000 (UTC) (envelope-from nobody@FreeBSD.org) Received: from www.freebsd.org (www.freebsd.org [IPv6:2001:4f8:fff6::21]) by mx1.freebsd.org (Postfix) with ESMTP id 329D18FC1C for ; Sat, 30 May 2009 15:03:40 +0000 (UTC) (envelope-from nobody@FreeBSD.org) Received: from www.freebsd.org (localhost [127.0.0.1]) by www.freebsd.org (8.14.3/8.14.3) with ESMTP id n4UF3dbC054085 for ; Sat, 30 May 2009 15:03:39 GMT (envelope-from nobody@www.freebsd.org) Received: (from nobody@localhost) by www.freebsd.org (8.14.3/8.14.3/Submit) id n4UF3dlb054084; Sat, 30 May 2009 15:03:39 GMT (envelope-from nobody) Message-Id: <200905301503.n4UF3dlb054084@www.freebsd.org> Date: Sat, 30 May 2009 15:03:39 GMT From: Jille Timmermans To: freebsd-gnats-submit@FreeBSD.org X-Send-Pr-Version: www-3.1 Cc: Subject: www/135078: [patch] apache22-peruser-mpm: dc2 -> dc3 X-BeenThere: freebsd-www@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: FreeBSD Project Webmasters List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 30 May 2009 15:10:03 -0000 >Number: 135078 >Category: www >Synopsis: [patch] apache22-peruser-mpm: dc2 -> dc3 >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-www >State: open >Quarter: >Keywords: >Date-Required: >Class: maintainer-update >Submitter-Id: current-users >Arrival-Date: Sat May 30 15:10:03 UTC 2009 >Closed-Date: >Last-Modified: >Originator: Jille Timmermans >Release: >Organization: >Environment: >Description: Update the dc2 patch to the newer version: dc3 - added Lazy's fix for graceful restarts (thanks for that!) - fixed chroot which was broken with dc2 patch. - optional support for cgroups. This is good for monitoring user's memory and cpu usage (or even limiting it). Format inside tag is: "Cgroup ". - the "request will not be honoured" error should now have more details about the processor and virtualhost. - added "MaxSpareProcessors" directive. This tells the server to start killing idle children if there are more than MaxSpareProcessors of them. Should help to reduce memory usage, but it may also reduce server speed (and/or increase cpu usage) if the children keep dying and respawning all the time. Default is off. - implemented the use of READY child status. This is used to get more accurate state of processors' and workers' status by manually setting it before accepting the new connection (and manually setting it to ACTIVE after we have received a connection). Not sure if it changes anything, but I think it's the cleaner way to go. - the default ProcessorWaitTimeout was increased from 2 to 5. >How-To-Repeat: >Fix: Patch attached with submission follows: diff -Nur apache22-peruser-mpm/Makefile apache22-peruser-mpm3/Makefile --- apache22-peruser-mpm/Makefile 2009-05-19 04:04:29.000000000 +0200 +++ apache22-peruser-mpm3/Makefile 2009-05-30 16:55:42.000000000 +0200 @@ -1,15 +1,15 @@ -# New ports collection makefile for: apache22-peruser -# Apache 2.2.X with peruser mpm 0.3.0-dc2 +# New ports collection makefile for: apache22-peruser-mpm +# Apache 2.2.X with peruser mpm 0.3.0-dc3 # Date created: 13 Sep 2008 # Whom: Jille Timmermans # Peruser main url: http://telana.com/peruser.php # Peruser patches: http://source.kood.ee/ -# This port contains the main patch, including the dc2 patch +# This port contains the main patch, including the dc3 patch # # $FreeBSD: ports/www/apache22-peruser-mpm/Makefile,v 1.4 2009/05/19 02:04:29 pgollucci Exp $ # -PORTREVISION= 2 +PORTREVISION= 3 MAINTAINER= jille@quis.cx @@ -17,7 +17,7 @@ SLAVE_PORT_MPM= peruser EXTRA_PATCHES+= ${.CURDIR}/files/httpd-2.2.3-peruser-0.3.0.patch -EXTRA_PATCHES+= ${.CURDIR}/files/httpd-2.2.3-peruser-0.3.0-dc2.patch +EXTRA_PATCHES+= ${.CURDIR}/files/httpd-2.2.3-peruser-0.3.0-dc3.patch WITH_MPM= ${SLAVE_PORT_MPM} SLAVE_DESIGNED_FOR= 2.2.11 # 2.2.3 to be honest, but works fine on 2.2.11 diff -Nur apache22-peruser-mpm/files/httpd-2.2.3-peruser-0.3.0-dc2.patch apache22-peruser-mpm3/files/httpd-2.2.3-peruser-0.3.0-dc2.patch --- apache22-peruser-mpm/files/httpd-2.2.3-peruser-0.3.0-dc2.patch 2008-12-15 23:20:23.000000000 +0100 +++ apache22-peruser-mpm3/files/httpd-2.2.3-peruser-0.3.0-dc2.patch 1970-01-01 01:00:00.000000000 +0100 @@ -1,844 +0,0 @@ ---- server/mpm/experimental/peruser/peruser.c 2008-05-16 16:10:21.000000000 +0300 -+++ server/mpm/experimental/peruser/peruser.c 2008-05-19 09:14:04.000000000 +0300 -@@ -206,9 +206,14 @@ - static int ap_min_processors=DEFAULT_MIN_PROCESSORS; - static int ap_min_free_processors=DEFAULT_MIN_FREE_PROCESSORS; - static int ap_max_processors=DEFAULT_MAX_PROCESSORS; -+static int ap_min_multiplexers=DEFAULT_MIN_MULTIPLEXERS; -+static int ap_max_multiplexers=DEFAULT_MAX_MULTIPLEXERS; - static int ap_daemons_limit=0; /* MaxClients */ --static int expire_timeout=1800; --static int idle_timeout=900; -+static int expire_timeout=DEFAULT_EXPIRE_TIMEOUT; -+static int idle_timeout=DEFAULT_IDLE_TIMEOUT; -+static int multiplexer_idle_timeout=DEFAULT_MULTIPLEXER_IDLE_TIMEOUT; -+static int processor_wait_timeout=DEFAULT_PROCESSOR_WAIT_TIMEOUT; -+static int processor_wait_steps=DEFAULT_PROCESSOR_WAIT_STEPS; - static int server_limit = DEFAULT_SERVER_LIMIT; - static int first_server_limit; - static int changed_limit_at_restart; -@@ -221,16 +226,20 @@ - typedef struct - { - int processor_id; -- -+ -+ const char *name; /* Server environment's unique string identifier */ -+ - /* security settings */ - uid_t uid; /* user id */ - gid_t gid; /* group id */ - const char *chroot; /* directory to chroot() to, can be null */ -+ int nice_lvl; - - /* resource settings */ - int min_processors; - int min_free_processors; - int max_processors; -+ int availability; - - /* sockets */ - int input; /* The socket descriptor */ -@@ -437,6 +446,25 @@ - return "UNKNOWN"; - } - -+char* scoreboard_status_string(int status) { -+ switch(status) -+ { -+ case SERVER_DEAD: return "DEAD"; -+ case SERVER_STARTING: return "STARTING"; -+ case SERVER_READY: return "READY"; -+ case SERVER_BUSY_READ: return "BUSY_READ"; -+ case SERVER_BUSY_WRITE: return "BUSY_WRITE"; -+ case SERVER_BUSY_KEEPALIVE: return "BUSY_KEEPALIVE"; -+ case SERVER_BUSY_LOG: return "BUSY_LOG"; -+ case SERVER_BUSY_DNS: return "BUSY_DNS"; -+ case SERVER_CLOSING: return "CLOSING"; -+ case SERVER_GRACEFUL: return "GRACEFUL"; -+ case SERVER_NUM_STATUS: return "NUM_STATUS"; -+ } -+ -+ return "UNKNOWN"; -+} -+ - void dump_child_table() - { - #ifdef MPM_PERUSER_DEBUG -@@ -1116,7 +1144,7 @@ - apr_bucket *bucket; - const apr_array_header_t *headers_in_array; - const apr_table_entry_t *headers_in; -- int counter; -+ int counter, wait_time, wait_step_size; - - apr_socket_t *thesock = ap_get_module_config(r->connection->conn_config, &core_module); - -@@ -1137,6 +1165,63 @@ - apr_table_get(r->headers_in, "Host"), my_child_num, processor->senv->output); - _DBG("r->the_request=\"%s\" len=%d", r->the_request, strlen(r->the_request)); - -+ wait_step_size = 100 / processor_wait_steps; -+ -+ /* Check if the processor is available */ -+ if (total_processors(processor->id) == processor->senv->max_processors && -+ idle_processors(processor->id) == 0) { -+ /* The processor is currently busy, try to wait (a little) */ -+ _DBG("processor seems to be busy, trying to wait for it"); -+ -+ if (processor->senv->availability == 0) { -+ processor->senv->availability = 0; -+ -+ _DBG("processor is very busy (availability = 0) - not passing request"); -+ /* No point in waiting for the processor, it's very busy */ -+ return -1; -+ } -+ -+ /* We sleep a little (depending how available the processor usually is) */ -+ int i; -+ -+ wait_time = (processor_wait_timeout / processor_wait_steps) * 1000000; -+ -+ for(i = 0; i <= processor->senv->availability; i += wait_step_size) { -+ usleep(wait_time); -+ -+ /* Check if the processor is ready */ -+ if (total_processors(processor->id) < processor->senv->max_processors || -+ idle_processors(processor->id) > 0) { -+ /* The processor has freed - lets use it */ -+ _DBG("processor freed before wait time expired"); -+ break; -+ } -+ } -+ -+ if (processor->senv->availability <= wait_step_size) { -+ processor->senv->availability = 0; -+ } -+ else processor->senv->availability -= wait_step_size; -+ -+ /* Check if we waited all the time */ -+ if (i > processor->senv->availability) { -+ _DBG("processor is busy - not passing request (availability = %d)", -+ processor->senv->availability); -+ return -1; -+ } -+ -+ /* We could increase the availability a little here, -+ * because the processor got freed eventually -+ */ -+ } -+ else { -+ /* Smoothly increment the availability back to 100 */ -+ if (processor->senv->availability >= 100-wait_step_size) { -+ processor->senv->availability = 100; -+ } -+ else processor->senv->availability += wait_step_size; -+ } -+ - ap_get_brigade(r->connection->input_filters, bb, AP_MODE_EXHAUSTIVE, APR_NONBLOCK_READ, len); - - /* Scan the brigade looking for heap-buckets */ -@@ -1402,6 +1487,10 @@ - static int peruser_setup_child(int childnum) - { - server_env_t *senv = CHILD_INFO_TABLE[childnum].senv; -+ -+ if (senv->nice_lvl != 0) { -+ nice(senv->nice_lvl); -+ } - - if(senv->chroot) { - _DBG("chdir to %s", senv->chroot); -@@ -1599,7 +1688,8 @@ - _DBG("updating processor stati", 0); - for(i = 0; i < NUM_CHILDS; ++i) - { -- if(CHILD_INFO_TABLE[i].status == CHILD_STATUS_READY) -+ if(CHILD_INFO_TABLE[i].type != CHILD_TYPE_MULTIPLEXER && -+ CHILD_INFO_TABLE[i].status == CHILD_STATUS_READY) - CHILD_INFO_TABLE[i].status = CHILD_STATUS_ACTIVE; - } - -@@ -1740,7 +1830,8 @@ - } - - if (CHILD_INFO_TABLE[my_child_num].type == CHILD_TYPE_PROCESSOR || -- CHILD_INFO_TABLE[my_child_num].type == CHILD_TYPE_WORKER) -+ CHILD_INFO_TABLE[my_child_num].type == CHILD_TYPE_WORKER || -+ CHILD_INFO_TABLE[my_child_num].type == CHILD_TYPE_MULTIPLEXER) - { - _DBG("CHECKING IF WE SHOULD CLONE A CHILD..."); - -@@ -1752,10 +1843,14 @@ - idle_processors(my_child_num), - CHILD_INFO_TABLE[my_child_num].senv->min_free_processors); - -- if(total_processors(my_child_num) < -+ if( -+ total_processors(my_child_num) < - CHILD_INFO_TABLE[my_child_num].senv->max_processors && -- idle_processors(my_child_num) <= -- CHILD_INFO_TABLE[my_child_num].senv->min_free_processors) -+ (idle_processors(my_child_num) <= -+ CHILD_INFO_TABLE[my_child_num].senv->min_free_processors || -+ total_processors(my_child_num) < -+ CHILD_INFO_TABLE[my_child_num].senv->min_processors -+ )) - { - _DBG("CLONING CHILD"); - child_clone(); -@@ -1804,22 +1899,55 @@ - clean_child_exit(0); - } - --static server_env_t* senv_add(int uid, int gid, const char* chroot) --{ -+static server_env_t* find_senv_by_name(const char *name) { - int i; -- int socks[2]; -+ -+ if (name == NULL) return NULL; -+ -+ _DBG("name=%s", name); - -- _DBG("Searching for matching senv..."); -+ for(i = 0; i < NUM_SENV; i++) -+ { -+ if(SENV[i].name != NULL && !strcmp(SENV[i].name, name)) { -+ return &SENV[i]; -+ } -+ } -+ -+ return NULL; -+} -+ -+static server_env_t* find_matching_senv(server_env_t* senv) { -+ int i; -+ -+ _DBG("name=%s uid=%d gid=%d chroot=%s", senv->name, senv->uid, senv->gid, senv->chroot); - - for(i = 0; i < NUM_SENV; i++) - { -- if(SENV[i].uid == uid && SENV[i].gid == gid && -- (SENV[i].chroot == NULL || !strcmp(SENV[i].chroot, chroot))) -- { -- _DBG("Found existing senv: %i", i); -+ if((senv->name != NULL && SENV[i].name != NULL && !strcmp(SENV[i].name, senv->name)) || -+ (senv->name == NULL && SENV[i].uid == senv->uid && SENV[i].gid == senv->gid && -+ ((SENV[i].chroot == NULL && senv->chroot == NULL) || ((SENV[i].chroot != NULL || senv->chroot != NULL) && !strcmp(SENV[i].chroot, senv->chroot)))) -+ ) { - return &SENV[i]; - } - } -+ -+ return NULL; -+} -+ -+static server_env_t* senv_add(server_env_t *senv) -+{ -+ int socks[2]; -+ server_env_t *old_senv; -+ -+ _DBG("Searching for matching senv..."); -+ -+ old_senv = find_matching_senv(senv); -+ -+ if (old_senv) { -+ _DBG("Found existing senv"); -+ senv = old_senv; -+ return old_senv; -+ } - - if(NUM_SENV >= server_limit) - { -@@ -1828,22 +1956,20 @@ - } - - _DBG("Creating new senv"); -+ -+ memcpy(&SENV[NUM_SENV], senv, sizeof(server_env_t)); - -- SENV[NUM_SENV].uid = uid; -- SENV[NUM_SENV].gid = gid; -- SENV[NUM_SENV].chroot = chroot; -- -- SENV[NUM_SENV].min_processors = ap_min_processors; -- SENV[NUM_SENV].min_free_processors = ap_min_free_processors; -- SENV[NUM_SENV].max_processors = ap_max_processors; -+ SENV[NUM_SENV].availability = 100; - - socketpair(PF_UNIX, SOCK_STREAM, 0, socks); - SENV[NUM_SENV].input = socks[0]; - SENV[NUM_SENV].output = socks[1]; -- -+ -+ senv = &SENV[NUM_SENV]; - return &SENV[server_env_image->control->num++]; - } - -+ - static const char* child_clone() - { - int i; -@@ -1869,7 +1995,12 @@ - new = &CHILD_INFO_TABLE[i]; - - new->senv = this->senv; -- new->type = CHILD_TYPE_WORKER; -+ if (this->type == CHILD_TYPE_MULTIPLEXER) { -+ new->type = CHILD_TYPE_MULTIPLEXER; -+ } -+ else { -+ new->type = CHILD_TYPE_WORKER; -+ } - new->sock_fd = this->sock_fd; - new->status = CHILD_STATUS_STARTING; - -@@ -1878,7 +2009,7 @@ - } - - static const char* child_add(int type, int status, -- apr_pool_t *pool, uid_t uid, gid_t gid, const char* chroot) -+ apr_pool_t *pool, server_env_t *senv) - { - _DBG("adding child #%d", NUM_CHILDS); - -@@ -1888,10 +2019,10 @@ - "Increase NumServers in your config file."; - } - -- if (chroot && !ap_is_directory(pool, chroot)) -- return apr_psprintf(pool, "Error: chroot directory [%s] does not exist", chroot); -+ if (senv->chroot && !ap_is_directory(pool, senv->chroot)) -+ return apr_psprintf(pool, "Error: chroot directory [%s] does not exist", senv->chroot); - -- CHILD_INFO_TABLE[NUM_CHILDS].senv = senv_add(uid, gid, chroot); -+ CHILD_INFO_TABLE[NUM_CHILDS].senv = senv_add(senv); - - if(CHILD_INFO_TABLE[NUM_CHILDS].senv == NULL) - { -@@ -1907,10 +2038,10 @@ - CHILD_INFO_TABLE[NUM_CHILDS].status = status; - - _DBG("[%d] uid=%d gid=%d type=%d chroot=%s", -- NUM_CHILDS, uid, gid, type, -- chroot); -+ NUM_CHILDS, senv->uid, senv->gid, type, -+ senv->chroot); - -- if (uid == 0 || gid == 0) -+ if (senv->uid == 0 || senv->gid == 0) - { - _DBG("Assigning root user/group to a child.", 0); - } -@@ -2062,19 +2193,28 @@ - if(CHILD_INFO_TABLE[i].status == CHILD_STATUS_STARTING) - make_child(ap_server_conf, i); - } -- else if(((CHILD_INFO_TABLE[i].type == CHILD_TYPE_PROCESSOR || -+ else if( -+ (((CHILD_INFO_TABLE[i].type == CHILD_TYPE_PROCESSOR || - CHILD_INFO_TABLE[i].type == CHILD_TYPE_WORKER) && - ap_scoreboard_image->parent[i].pid > 1) && -- (idle_processors (i) > 1 || total_processes (i) == 1) && ( -+ (idle_processors (i) > CHILD_INFO_TABLE[i].senv->min_free_processors || CHILD_INFO_TABLE[i].senv->min_free_processors == 0) -+ && total_processes (i) > CHILD_INFO_TABLE[i].senv->min_processors && ( - (expire_timeout > 0 && ap_scoreboard_image->servers[i][0].status != SERVER_DEAD && - apr_time_sec(now - ap_scoreboard_image->servers[i][0].last_used) > expire_timeout) || - (idle_timeout > 0 && ap_scoreboard_image->servers[i][0].status == SERVER_READY && -- apr_time_sec(now - ap_scoreboard_image->servers[i][0].last_used) > idle_timeout))) -+ apr_time_sec(now - ap_scoreboard_image->servers[i][0].last_used) > idle_timeout)) -+ ) -+ || (CHILD_INFO_TABLE[i].type == CHILD_TYPE_MULTIPLEXER && -+ (multiplexer_idle_timeout > 0 && ap_scoreboard_image->servers[i][0].status == SERVER_READY && -+ apr_time_sec(now - ap_scoreboard_image->servers[i][0].last_used) > multiplexer_idle_timeout) && -+ total_processors(i) > CHILD_INFO_TABLE[i].senv->min_processors -+ ) -+ ) - { - CHILD_INFO_TABLE[i].pid = 0; - CHILD_INFO_TABLE[i].status = CHILD_STATUS_STANDBY; - -- if(CHILD_INFO_TABLE[i].type == CHILD_TYPE_WORKER) -+ if(CHILD_INFO_TABLE[i].type == CHILD_TYPE_WORKER || CHILD_INFO_TABLE[i].type == CHILD_TYPE_MULTIPLEXER) - { - /* completely free up this slot */ - -@@ -2599,6 +2739,8 @@ - ap_min_processors = DEFAULT_MIN_PROCESSORS; - ap_min_free_processors = DEFAULT_MIN_FREE_PROCESSORS; - ap_max_processors = DEFAULT_MAX_PROCESSORS; -+ ap_min_multiplexers = DEFAULT_MIN_MULTIPLEXERS; -+ ap_max_multiplexers = DEFAULT_MAX_MULTIPLEXERS; - ap_daemons_limit = server_limit; - ap_pid_fname = DEFAULT_PIDLOG; - ap_lock_fname = DEFAULT_LOCKFILE; -@@ -2608,6 +2750,13 @@ - ap_max_mem_free = APR_ALLOCATOR_MAX_FREE_UNLIMITED; - #endif - -+ expire_timeout = DEFAULT_EXPIRE_TIMEOUT; -+ idle_timeout = DEFAULT_IDLE_TIMEOUT; -+ multiplexer_idle_timeout = DEFAULT_MULTIPLEXER_IDLE_TIMEOUT; -+ processor_wait_timeout = DEFAULT_PROCESSOR_WAIT_TIMEOUT; -+ processor_wait_steps = DEFAULT_PROCESSOR_WAIT_STEPS; -+ -+ - apr_cpystrn(ap_coredump_dir, ap_server_root, sizeof(ap_coredump_dir)); - - /* we need to know ServerLimit and ThreadLimit before we start processing -@@ -2712,6 +2861,7 @@ - - server_env_image->control->num = 0; - -+/* - for (i = 0; i < tmp_server_limit; i++) - { - SENV[i].processor_id = -1; -@@ -2721,6 +2871,7 @@ - SENV[i].input = -1; - SENV[i].output = -1; - } -+*/ - } - - return OK; -@@ -2782,7 +2933,6 @@ - { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, - ap_server_conf, "Could not pass request to proper " "child, request will not be honoured."); -- return DECLINED; - } - _DBG("doing longjmp",0); - longjmp(CHILD_INFO_TABLE[my_child_num].jmpbuffer, 1); -@@ -2859,32 +3009,37 @@ - ap_rputs("
\n", r); - ap_rputs("

peruser status

\n", r); - ap_rputs("\n", r); -- ap_rputs("" -- "" -+ ap_rputs("" -+ "" - "" - "" -- "\n", r); -+ "" -+ "" -+ "\n", r); - for (x = 0; x < NUM_CHILDS; x++) - { - senv = CHILD_INFO_TABLE[x].senv; -- ap_rprintf(r, "" -- "" -+ ap_rprintf(r, "" -+ "" - "" -- "\n", -+ "\n", - CHILD_INFO_TABLE[x].id, - CHILD_INFO_TABLE[x].pid, - child_status_string(CHILD_INFO_TABLE[x].status), -+ scoreboard_status_string(SCOREBOARD_STATUS(x)), - child_type_string(CHILD_INFO_TABLE[x].type), - senv == NULL ? -1 : senv->uid, - senv == NULL ? -1 : senv->gid, - senv == NULL ? NULL : senv->chroot, -+ senv == NULL ? 0 : senv->nice_lvl, - senv == NULL ? -1 : CHILD_INFO_TABLE[x].senv->input, - senv == NULL ? -1 : CHILD_INFO_TABLE[x].senv->output, - CHILD_INFO_TABLE[x].sock_fd, - total_processors(x), - senv == NULL ? -1 : CHILD_INFO_TABLE[x].senv->max_processors, - idle_processors(x), -- senv == NULL ? -1 : CHILD_INFO_TABLE[x].senv->min_free_processors -+ senv == NULL ? -1 : CHILD_INFO_TABLE[x].senv->min_free_processors, -+ senv == NULL ? -1 : CHILD_INFO_TABLE[x].senv->availability - ); - } - ap_rputs("
IDPIDSTATUSTYPEUIDGIDCHROOTINPUT
IDPIDSTATUSSB STATUSTYPEUIDGIDCHROOTNICEINPUTOUTPUTSOCK_FDTOTAL PROCESSORSMAX PROCESSORSIDLE PROCESSORSMIN FREE PROCESSORS
IDLE PROCESSORSMIN FREE PROCESSORSAVAIL
%3d%5d%8s%12s%4d%4d%25s%5d
%3d%5d%8s%8s%12s%4d%4d%25s%3d%5d%6d%7d%d%d%d%d
%d%d%3d
\n", r); -@@ -2938,50 +3093,162 @@ - APR_OPTIONAL_HOOK(ap, status_hook, peruser_status_hook, NULL, NULL, APR_HOOK_MIDDLE); - } - --/* we define an Processor w/ specific uid/gid */ --static const char *cf_Processor(cmd_parms *cmd, void *dummy, -- const char *user_name, const char *group_name, const char *chroot) -+static const char *cf_Processor(cmd_parms *cmd, void *dummy, const char *arg) - { -- uid_t uid = ap_uname2id(user_name); -- gid_t gid = ap_gname2id(group_name); -+ const char *user_name = NULL, *group_name = NULL, *directive; -+ server_env_t senv; -+ ap_directive_t *current; -+ -+ char *endp = ap_strrchr_c(arg, '>'); -+ -+ if (endp == NULL) { -+ return apr_psprintf(cmd->temp_pool, -+ "Error: Directive %s> missing closing '>'", cmd->cmd->name); -+ } -+ -+ *endp = '\0'; -+ -+ senv.name = ap_getword_conf(cmd->temp_pool, &arg); -+ _DBG("processor_name: %s", senv.name); -+ -+ if (strlen(senv.name) == 0) { -+ return apr_psprintf(cmd->temp_pool, -+ "Error: Directive %s> takes one argument", cmd->cmd->name); -+ } -+ -+ /* Check for existing processors on first launch and between gracefuls */ -+ if (restart_num == 1 || is_graceful) { -+ server_env_t *old_senv = find_senv_by_name(senv.name); -+ -+ if (old_senv) { -+ return apr_psprintf(cmd->temp_pool, -+ "Error: Processor %s already defined", senv.name); -+ } -+ } -+ -+ senv.nice_lvl = 0; -+ senv.chroot = NULL; -+ senv.min_processors = ap_min_processors; -+ senv.min_free_processors = ap_min_free_processors; -+ senv.max_processors = ap_max_processors; -+ -+ current = cmd->directive->first_child; -+ -+ int proc_temp = 0; -+ -+ for(; current != NULL; current = current->next) { -+ directive = current->directive; -+ -+ if (!strcasecmp(directive, "user")) { -+ user_name = current->args; -+ } -+ else if (!strcasecmp(directive, "group")) { -+ group_name = current->args; -+ } -+ else if (!strcasecmp(directive, "chroot")) { -+ senv.chroot = current->args; -+ } -+ else if (!strcasecmp(directive, "nicelevel")) { -+ senv.nice_lvl = atoi(current->args); -+ } -+ else if (!strcasecmp(directive, "maxprocessors")) { -+ proc_temp = atoi(current->args); -+ -+ if (proc_temp < 1) { -+ ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, -+ "WARNING: Require MaxProcessors > 0, setting to 1"); -+ proc_temp = 1; -+ } -+ -+ senv.max_processors = proc_temp; -+ } -+ else if (!strcasecmp(directive, "minprocessors")) { -+ proc_temp = atoi(current->args); -+ -+ if (proc_temp < 0) { -+ ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, -+ "WARNING: Require MinProcessors >= 0, setting to 0"); -+ proc_temp = 0; -+ } -+ -+ senv.min_processors = proc_temp; -+ } -+ else if (!strcasecmp(directive, "minspareprocessors")) { -+ proc_temp = atoi(current->args); -+ -+ if (proc_temp < 0) { -+ ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, -+ "WARNING: Require MinSpareProcessors >= 0, setting to 0"); -+ proc_temp = 0; -+ } -+ -+ senv.min_free_processors = proc_temp; -+ } -+ else { -+ ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, -+ "Unknown directive %s in %s>", directive, cmd->cmd->name); -+ } -+ } -+ -+ if (user_name == NULL || group_name == NULL) { -+ return apr_psprintf(cmd->temp_pool, -+ "Error: User or Group must be set in %s>", cmd->cmd->name); -+ } -+ -+ senv.uid = ap_uname2id(user_name); -+ senv.gid = ap_gname2id(group_name); -+ -+ _DBG("name=%s user=%s:%d group=%s:%d chroot=%s nice_lvl=%d", -+ senv.name, user_name, senv.uid, group_name, senv.gid, senv.chroot, senv.nice_lvl); -+ -+ _DBG("min_processors=%d min_free_processors=%d max_processors=%d", -+ senv.min_processors, senv.min_free_processors, senv.max_processors); - -- _DBG("user=%s:%d group=%s:%d chroot=%s", -- user_name, uid, group_name, gid, chroot); - - return child_add(CHILD_TYPE_PROCESSOR, CHILD_STATUS_STANDBY, -- cmd->pool, uid, gid, chroot); -+ cmd->pool, &senv); - } - - /* we define an Multiplexer child w/ specific uid/gid */ - static const char *cf_Multiplexer(cmd_parms *cmd, void *dummy, - const char *user_name, const char *group_name, const char *chroot) - { -- uid_t uid = ap_uname2id(user_name); -- gid_t gid = ap_gname2id(group_name); -+ server_env_t senv; -+ -+ senv.name = NULL; -+ -+ senv.uid = ap_uname2id(user_name); -+ senv.gid = ap_gname2id(group_name); -+ senv.chroot = chroot; -+ senv.nice_lvl = 0; -+ -+ senv.min_processors = ap_min_multiplexers; -+ senv.min_free_processors = ap_min_free_processors; -+ senv.max_processors = ap_max_multiplexers; - - _DBG("user=%s:%d group=%s:%d chroot=%s [multiplexer id %d]", -- user_name, uid, group_name, gid, chroot, NUM_CHILDS); -+ user_name, senv.uid, group_name, senv.gid, senv.chroot, NUM_CHILDS); - - return child_add(CHILD_TYPE_MULTIPLEXER, CHILD_STATUS_STARTING, -- cmd->pool, uid, gid, chroot); -+ cmd->pool, &senv); - } - - static const char* cf_ServerEnvironment(cmd_parms *cmd, void *dummy, -- const char *user_name, const char *group_name, const char *chroot) -+ const char *name) - { -- int uid = ap_uname2id(user_name); -- int gid = ap_gname2id(group_name); - peruser_server_conf *sconf = PERUSER_SERVER_CONF(cmd->server->module_config); - - _DBG("function entered", 0); - -- if (chroot && !ap_is_directory(cmd->pool, chroot)) -- return apr_psprintf(cmd->pool, "Error: chroot directory [%s] does not exist", chroot); -+ sconf->senv = find_senv_by_name(name); - -- sconf->senv = senv_add(uid, gid, chroot); -+ if (sconf->senv == NULL) { -+ return apr_psprintf(cmd->pool, -+ "Error: Processor %s not defined", name); -+ } - -- _DBG("user=%s:%d group=%s:%d chroot=%s numchilds=%d", -- user_name, uid, group_name, gid, chroot, NUM_CHILDS); -+ _DBG("user=%d group=%d chroot=%s numchilds=%d", -+ sconf->senv->uid, sconf->senv->gid, sconf->senv->chroot, NUM_CHILDS); - - return NULL; - } -@@ -3046,10 +3313,10 @@ - - min_procs = atoi(arg); - -- if (min_procs < 1) { -+ if (min_procs < 0) { - ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, -- "WARNING: Require MaxProcessors > 0, setting to 1"); -- min_procs = 1; -+ "WARNING: Require MinProcessors >= 0, setting to 0"); -+ min_procs = 0; - } - - if (ap_check_cmd_context(cmd, NOT_IN_VIRTUALHOST) != NULL) { -@@ -3075,10 +3342,10 @@ - - min_free_procs = atoi(arg); - -- if (min_free_procs < 1) { -+ if (min_free_procs < 0) { - ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, -- "WARNING: Require MinSpareProcessors > 0, setting to 1"); -- min_free_procs = 1; -+ "WARNING: Require MinSpareProcessors >= 0, setting to 0"); -+ min_free_procs = 0; - } - - if (ap_check_cmd_context(cmd, NOT_IN_VIRTUALHOST) != NULL) { -@@ -3121,6 +3388,50 @@ - return NULL; - } - -+static const char *set_min_multiplexers (cmd_parms *cmd, void *dummy, const char *arg) -+{ -+ int min_multiplexers; -+ const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT); -+ -+ if (err != NULL) { -+ return err; -+ } -+ -+ min_multiplexers = atoi(arg); -+ -+ if (min_multiplexers < 1) { -+ ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, -+ "WARNING: Require MinMultiplexers > 0, setting to 1"); -+ min_multiplexers = 1; -+ } -+ -+ ap_min_multiplexers = min_multiplexers; -+ -+ return NULL; -+} -+ -+static const char *set_max_multiplexers (cmd_parms *cmd, void *dummy, const char *arg) -+{ -+ int max_multiplexers; -+ const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT); -+ -+ if (err != NULL) { -+ return err; -+ } -+ -+ max_multiplexers = atoi(arg); -+ -+ if (max_multiplexers < 1) { -+ ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, -+ "WARNING: Require MaxMultiplexers > 0, setting to 1"); -+ max_multiplexers = 1; -+ } -+ -+ ap_max_multiplexers = max_multiplexers; -+ -+ return NULL; -+} -+ - static const char *set_server_limit (cmd_parms *cmd, void *dummy, const char *arg) - { - int tmp_server_limit; -@@ -3183,6 +3494,40 @@ - return NULL; - } - -+static const char *set_multiplexer_idle_timeout (cmd_parms *cmd, void *dummy, const char *arg) { -+ const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); -+ if (err != NULL) { -+ return err; -+ } -+ -+ multiplexer_idle_timeout = atoi(arg); -+ -+ return NULL; -+} -+ -+static const char *set_processor_wait_timeout (cmd_parms *cmd, void *dummy, const char *timeout, const char *steps) { -+ const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); -+ if (err != NULL) { -+ return err; -+ } -+ -+ processor_wait_timeout = atoi(timeout); -+ -+ if (steps != NULL) { -+ int steps_tmp = atoi(steps); -+ -+ if (steps_tmp < 1) { -+ ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, -+ "WARNING: Require ProcessorWaitTimeout steps > 0, setting to 1"); -+ steps_tmp = 1; -+ } -+ -+ processor_wait_steps = steps_tmp; -+ } -+ -+ return NULL; -+} -+ - static const command_rec peruser_cmds[] = { - UNIX_DAEMON_COMMANDS, - LISTEN_COMMANDS, -@@ -3196,17 +3541,25 @@ - "Minimum number of processors per vhost"), - AP_INIT_TAKE1("MaxProcessors", set_max_processors, NULL, RSRC_CONF, - "Maximum number of processors per vhost"), -+AP_INIT_TAKE1("MinMultiplexers", set_min_multiplexers, NULL, RSRC_CONF, -+ "Minimum number of multiplexers the server can have"), -+AP_INIT_TAKE1("MaxMultiplexers", set_max_multiplexers, NULL, RSRC_CONF, -+ "Maximum number of multiplexers the server can have"), - AP_INIT_TAKE1("ServerLimit", set_server_limit, NULL, RSRC_CONF, - "Maximum value of MaxClients for this run of Apache"), - AP_INIT_TAKE1("ExpireTimeout", set_expire_timeout, NULL, RSRC_CONF, -- "Maximum idle time before a child is killed, 0 to disable"), -+ "Maximum time a child can live, 0 to disable"), - AP_INIT_TAKE1("IdleTimeout", set_idle_timeout, NULL, RSRC_CONF, - "Maximum time before a child is killed after being idle, 0 to disable"), -+AP_INIT_TAKE1("MultiplexerIdleTimeout", set_multiplexer_idle_timeout, NULL, RSRC_CONF, -+ "Maximum time before a multiplexer is killed after being idle, 0 to disable"), -+AP_INIT_TAKE12("ProcessorWaitTimeout", set_processor_wait_timeout, NULL, RSRC_CONF, -+ "Maximum time a multiplexer waits for the processor if it is busy"), - AP_INIT_TAKE23("Multiplexer", cf_Multiplexer, NULL, RSRC_CONF, - "Specify an Multiplexer Child configuration."), --AP_INIT_TAKE23("Processor", cf_Processor, NULL, RSRC_CONF, -- "Specify a User and Group for a specific child process."), --AP_INIT_TAKE23("ServerEnvironment", cf_ServerEnvironment, NULL, RSRC_CONF, -+AP_INIT_RAW_ARGS("parent[i].pid) + #define MPM_NOTE_CHILD_KILLED(i) (MPM_CHILD_PID(i) = 0) ++#define MPM_VALID_PID(p) (getpgid(p) == getpgrp()) + #define MPM_ACCEPT_FUNC unixd_accept + + extern int ap_threads_per_child; +--- server/mpm/experimental/peruser/peruser.c 2009-05-27 15:09:19.000000000 +0300 ++++ server/mpm/experimental/peruser/peruser.c 2009-05-28 13:54:27.000000000 +0300 +@@ -195,20 +195,30 @@ + + #define CHILD_STATUS_STANDBY 0 /* wait for a request before starting */ + #define CHILD_STATUS_STARTING 1 /* wait for socket creation */ +-#define CHILD_STATUS_READY 2 /* wait for mux to restart */ +-#define CHILD_STATUS_ACTIVE 3 /* ready to take requests */ ++#define CHILD_STATUS_READY 2 /* is ready to take requests */ ++#define CHILD_STATUS_ACTIVE 3 /* is currently busy handling requests */ + #define CHILD_STATUS_RESTART 4 /* child about to die and restart */ + ++/* cgroup settings */ ++#define CGROUP_TASKS_FILE "/tasks" ++#define CGROUP_TASKS_FILE_LEN 7 ++ + /* config globals */ + + int ap_threads_per_child=0; /* Worker threads per child */ + static apr_proc_mutex_t *accept_mutex; + static int ap_min_processors=DEFAULT_MIN_PROCESSORS; + static int ap_min_free_processors=DEFAULT_MIN_FREE_PROCESSORS; ++static int ap_max_free_processors=DEFAULT_MAX_FREE_PROCESSORS; + static int ap_max_processors=DEFAULT_MAX_PROCESSORS; ++static int ap_min_multiplexers=DEFAULT_MIN_MULTIPLEXERS; ++static int ap_max_multiplexers=DEFAULT_MAX_MULTIPLEXERS; + static int ap_daemons_limit=0; /* MaxClients */ +-static int expire_timeout=1800; +-static int idle_timeout=900; ++static int expire_timeout=DEFAULT_EXPIRE_TIMEOUT; ++static int idle_timeout=DEFAULT_IDLE_TIMEOUT; ++static int multiplexer_idle_timeout=DEFAULT_MULTIPLEXER_IDLE_TIMEOUT; ++static int processor_wait_timeout=DEFAULT_PROCESSOR_WAIT_TIMEOUT; ++static int processor_wait_steps=DEFAULT_PROCESSOR_WAIT_STEPS; + static int server_limit = DEFAULT_SERVER_LIMIT; + static int first_server_limit; + static int changed_limit_at_restart; +@@ -222,15 +232,21 @@ + { + int processor_id; + ++ const char *name; /* Server environment's unique string identifier */ ++ + /* security settings */ + uid_t uid; /* user id */ + gid_t gid; /* group id */ + const char *chroot; /* directory to chroot() to, can be null */ ++ int nice_lvl; ++ const char *cgroup; /* cgroup directory, can be null */ + + /* resource settings */ + int min_processors; + int min_free_processors; ++ int max_free_processors; + int max_processors; ++ int availability; + + /* sockets */ + int input; /* The socket descriptor */ +@@ -437,6 +453,25 @@ + return "UNKNOWN"; + } + ++char* scoreboard_status_string(int status) { ++ switch(status) ++ { ++ case SERVER_DEAD: return "DEAD"; ++ case SERVER_STARTING: return "STARTING"; ++ case SERVER_READY: return "READY"; ++ case SERVER_BUSY_READ: return "BUSY_READ"; ++ case SERVER_BUSY_WRITE: return "BUSY_WRITE"; ++ case SERVER_BUSY_KEEPALIVE: return "BUSY_KEEPALIVE"; ++ case SERVER_BUSY_LOG: return "BUSY_LOG"; ++ case SERVER_BUSY_DNS: return "BUSY_DNS"; ++ case SERVER_CLOSING: return "CLOSING"; ++ case SERVER_GRACEFUL: return "GRACEFUL"; ++ case SERVER_NUM_STATUS: return "NUM_STATUS"; ++ } ++ ++ return "UNKNOWN"; ++} ++ + void dump_child_table() + { + #ifdef MPM_PERUSER_DEBUG +@@ -511,10 +546,6 @@ + + static void accept_mutex_on(void) + { +-/* for some reason this fails if we listen on the pipe_of_death. +- fortunately I don't think we currently need it */ +- +-#if 0 + apr_status_t rv = apr_proc_mutex_lock(accept_mutex); + if (rv != APR_SUCCESS) { + const char *msg = "couldn't grab the accept mutex"; +@@ -529,12 +560,10 @@ + exit(APEXIT_CHILDFATAL); + } + } +-#endif + } + + static void accept_mutex_off(void) + { +-#if 0 + apr_status_t rv = apr_proc_mutex_unlock(accept_mutex); + if (rv != APR_SUCCESS) { + const char *msg = "couldn't release the accept mutex"; +@@ -552,7 +581,6 @@ + exit(APEXIT_CHILDFATAL); + } + } +-#endif + } + + /* On some architectures it's safe to do unserialized accept()s in the single +@@ -715,8 +743,10 @@ + ret = apr_socket_recv(lr->sd, &pipe_read_char, &n); + if (APR_STATUS_IS_EAGAIN(ret)) + { +- /* It lost the lottery. It must continue to suffer +- * through a life of servitude. */ ++ /* It lost the lottery. It must continue to suffer ++ * through a life of servitude. */ ++ _DBG("POD read EAGAIN"); ++ return ret; + } + else + { +@@ -1087,8 +1117,7 @@ + for(i = 0, total = 0; i < NUM_CHILDS; ++i) + { + if(CHILD_INFO_TABLE[i].senv == CHILD_INFO_TABLE[child_num].senv && +- (SCOREBOARD_STATUS(i) == SERVER_STARTING || +- SCOREBOARD_STATUS(i) == SERVER_READY)) ++ (CHILD_INFO_TABLE[i].status == CHILD_STATUS_READY)) + { + total++; + } +@@ -1116,7 +1145,7 @@ + apr_bucket *bucket; + const apr_array_header_t *headers_in_array; + const apr_table_entry_t *headers_in; +- int counter; ++ int counter, wait_time, wait_step_size; + + apr_socket_t *thesock = ap_get_module_config(r->connection->conn_config, &core_module); + +@@ -1137,10 +1166,73 @@ + apr_table_get(r->headers_in, "Host"), my_child_num, processor->senv->output); + _DBG("r->the_request=\"%s\" len=%d", r->the_request, strlen(r->the_request)); + +- ap_get_brigade(r->connection->input_filters, bb, AP_MODE_EXHAUSTIVE, APR_NONBLOCK_READ, len); ++ wait_step_size = 100 / processor_wait_steps; + +- /* Scan the brigade looking for heap-buckets */ ++ /* Check if the processor is available */ ++ if (total_processors(processor->id) == processor->senv->max_processors && ++ idle_processors(processor->id) == 0) { ++ /* The processor is currently busy, try to wait (a little) */ ++ _DBG("processor seems to be busy, trying to wait for it"); ++ ++ if (processor->senv->availability == 0) { ++ processor->senv->availability = 0; ++ ++ _DBG("processor is very busy (availability = 0) - not passing request"); ++ ++ ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ap_server_conf, ++ "Too many requests for processor %s, increase MaxProcessors", processor->senv->name); ++ ++ /* No point in waiting for the processor, it's very busy */ ++ return -1; ++ } ++ ++ /* We sleep a little (depending how available the processor usually is) */ ++ int i; ++ ++ wait_time = (processor_wait_timeout / processor_wait_steps) * 1000000; ++ ++ for(i = 0; i <= processor->senv->availability; i += wait_step_size) { ++ usleep(wait_time); + ++ /* Check if the processor is ready */ ++ if (total_processors(processor->id) < processor->senv->max_processors || ++ idle_processors(processor->id) > 0) { ++ /* The processor has freed - lets use it */ ++ _DBG("processor freed before wait time expired"); ++ break; ++ } ++ } ++ ++ if (processor->senv->availability <= wait_step_size) { ++ processor->senv->availability = 0; ++ } ++ else processor->senv->availability -= wait_step_size; ++ ++ /* Check if we waited all the time */ ++ if (i > processor->senv->availability) { ++ _DBG("processor is busy - not passing request (availability = %d)", ++ processor->senv->availability); ++ ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ap_server_conf, ++ "Too many requests for processor %s, increase MaxProcessors", processor->senv->name); ++ return -1; ++ } ++ ++ /* We could increase the availability a little here, ++ * because the processor got freed eventually ++ */ ++ } ++ else { ++ /* Smoothly increment the availability back to 100 */ ++ if (processor->senv->availability >= 100-wait_step_size) { ++ processor->senv->availability = 100; ++ } ++ else processor->senv->availability += wait_step_size; ++ } ++ ++ ap_get_brigade(r->connection->input_filters, bb, AP_MODE_EXHAUSTIVE, APR_NONBLOCK_READ, len); ++ ++ /* Scan the brigade looking for heap-buckets */ ++ + _DBG("Scanning the brigade",0); + bucket = APR_BRIGADE_FIRST(bb); + while (bucket != APR_BRIGADE_SENTINEL(bb) && +@@ -1294,12 +1386,22 @@ + /* -- receive data from socket -- */ + apr_os_sock_get(&ctrl_sock_fd, lr->sd); + _DBG("receiving from sock_fd=%d", ctrl_sock_fd); +- ret = recvmsg(ctrl_sock_fd, &msg, 0); + +- if(ret == -1) +- _DBG("recvmsg failed with error \"%s\"", strerror(errno)); +- else +- _DBG("recvmsg returned %d", ret); ++ // Don't block ++ ret = recvmsg(ctrl_sock_fd, &msg, MSG_DONTWAIT); ++ ++ if (ret == -1 && errno == EAGAIN) { ++ _DBG("receive_from_multiplexer recvmsg() EAGAIN, someone was faster"); ++ ++ return APR_EAGAIN; ++ } ++ else if (ret == -1) { ++ _DBG("recvmsg failed with error \"%s\"", strerror(errno)); ++ ++ // Error, better kill this child to be on the safe side ++ return APR_EGENERAL; ++ } ++ else _DBG("recvmsg returned %d", ret); + + /* -- extract socket from the cmsg -- */ + memcpy(&trans_sock_fd, CMSG_DATA(cmsg), sizeof(trans_sock_fd)); +@@ -1399,10 +1501,58 @@ + return 0; + } + +-static int peruser_setup_child(int childnum) ++static int peruser_setup_cgroup(int childnum, server_env_t *senv, apr_pool_t *pool) ++{ ++ apr_file_t *file; ++ int length; ++ apr_size_t content_len; ++ char *tasks_file, *content, *pos; ++ ++ _DBG("starting to add pid to cgroup %s", senv->cgroup); ++ ++ length = strlen(senv->cgroup) + CGROUP_TASKS_FILE_LEN; ++ tasks_file = malloc(length); ++ ++ if (!tasks_file) return -1; ++ ++ pos = apr_cpystrn(tasks_file, senv->cgroup, length); ++ apr_cpystrn(pos, CGROUP_TASKS_FILE, CGROUP_TASKS_FILE_LEN); ++ ++ /* Prepare the data to be written to tasks file */ ++ content = apr_itoa(pool, ap_my_pid); ++ content_len = strlen(content); ++ ++ _DBG("writing pid %s to tasks file %s", content, tasks_file); ++ ++ if (apr_file_open(&file, tasks_file, APR_WRITE, APR_OS_DEFAULT, pool)) { ++ ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL, ++ "cgroup: unable to open file %s", ++ tasks_file); ++ free(tasks_file); ++ return OK; /* don't fail if cgroup not available */ ++ } ++ ++ if (apr_file_write(file, content, &content_len)) { ++ ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL, ++ "cgroup: unable to write pid to file %s", ++ tasks_file); ++ } ++ ++ apr_file_close(file); ++ ++ free(tasks_file); ++ ++ return OK; ++} ++ ++static int peruser_setup_child(int childnum, apr_pool_t *pool) + { + server_env_t *senv = CHILD_INFO_TABLE[childnum].senv; + ++ if (senv->nice_lvl != 0) { ++ nice(senv->nice_lvl); ++ } ++ + if(senv->chroot) { + _DBG("chdir to %s", senv->chroot); + if(chdir(senv->chroot)) { +@@ -1421,6 +1571,10 @@ + } + } + ++ if(senv->cgroup) { ++ peruser_setup_cgroup(childnum, senv, pool); ++ } ++ + if (senv->uid == -1 && senv->gid == -1) { + return unixd_setup_child(); + } +@@ -1594,15 +1748,6 @@ + { + case CHILD_TYPE_MULTIPLEXER: + _DBG("MULTIPLEXER %d", my_child_num); +- +- /* update status on processors that are ready to accept requests */ +- _DBG("updating processor stati", 0); +- for(i = 0; i < NUM_CHILDS; ++i) +- { +- if(CHILD_INFO_TABLE[i].status == CHILD_STATUS_READY) +- CHILD_INFO_TABLE[i].status = CHILD_STATUS_ACTIVE; +- } +- + break; + + case CHILD_TYPE_PROCESSOR: +@@ -1626,7 +1771,7 @@ + apr_os_sock_put(&pod_sock, &fd, pconf); + listen_add(pconf, pod_sock, check_pipe_of_death); + +- if(peruser_setup_child(my_child_num) != 0) ++ if(peruser_setup_child(my_child_num, pchild) != 0) + clean_child_exit(APEXIT_CHILDFATAL); + + ap_run_child_init(pchild, ap_server_conf); +@@ -1670,14 +1815,19 @@ + clean_child_exit(0); + } + +- (void) ap_update_child_status(sbh, SERVER_READY, (request_rec *) NULL); ++ (void) ap_update_child_status(sbh, SERVER_READY, (request_rec *) NULL); ++ ++ CHILD_INFO_TABLE[my_child_num].status = CHILD_STATUS_READY; ++ _DBG("Child %d (%s) is now ready", my_child_num, child_type_string(CHILD_INFO_TABLE[my_child_num].type)); + + /* + * Wait for an acceptable connection to arrive. + */ + +- /* Lock around "accept", if necessary */ +- SAFE_ACCEPT(accept_mutex_on()); ++ /* Lock around "accept", if necessary */ ++ if (CHILD_INFO_TABLE[my_child_num].type == CHILD_TYPE_MULTIPLEXER) { ++ SAFE_ACCEPT(accept_mutex_on()); ++ } + + if (num_listensocks == 1) { + offset = 0; +@@ -1729,18 +1879,27 @@ + * defer the exit + */ + status = listensocks[offset].accept_func((void *)&sock, &listensocks[offset], ptrans); +- SAFE_ACCEPT(accept_mutex_off()); /* unlock after "accept" */ ++ ++ if (CHILD_INFO_TABLE[my_child_num].type == CHILD_TYPE_MULTIPLEXER) { ++ SAFE_ACCEPT(accept_mutex_off()); /* unlock after "accept" */ ++ } + + if (status == APR_EGENERAL) { + /* resource shortage or should-not-occur occured */ + clean_child_exit(1); + } +- else if (status != APR_SUCCESS || die_now) { ++ else if (status != APR_SUCCESS || die_now || sock == NULL) { + continue; + } + ++ if (CHILD_INFO_TABLE[my_child_num].status == CHILD_STATUS_READY) { ++ CHILD_INFO_TABLE[my_child_num].status = CHILD_STATUS_ACTIVE; ++ _DBG("Child %d (%s) is now active", my_child_num, child_type_string(CHILD_INFO_TABLE[my_child_num].type)); ++ } ++ + if (CHILD_INFO_TABLE[my_child_num].type == CHILD_TYPE_PROCESSOR || +- CHILD_INFO_TABLE[my_child_num].type == CHILD_TYPE_WORKER) ++ CHILD_INFO_TABLE[my_child_num].type == CHILD_TYPE_WORKER || ++ CHILD_INFO_TABLE[my_child_num].type == CHILD_TYPE_MULTIPLEXER) + { + _DBG("CHECKING IF WE SHOULD CLONE A CHILD..."); + +@@ -1754,8 +1913,11 @@ + + if(total_processors(my_child_num) < + CHILD_INFO_TABLE[my_child_num].senv->max_processors && +- idle_processors(my_child_num) <= +- CHILD_INFO_TABLE[my_child_num].senv->min_free_processors) ++ (idle_processors(my_child_num) <= ++ CHILD_INFO_TABLE[my_child_num].senv->min_free_processors || ++ total_processors(my_child_num) < ++ CHILD_INFO_TABLE[my_child_num].senv->min_processors ++ )) + { + _DBG("CLONING CHILD"); + child_clone(); +@@ -1804,46 +1966,80 @@ + clean_child_exit(0); + } + +-static server_env_t* senv_add(int uid, int gid, const char* chroot) +-{ ++static server_env_t* find_senv_by_name(const char *name) { + int i; +- int socks[2]; + +- _DBG("Searching for matching senv..."); ++ if (name == NULL) return NULL; ++ ++ _DBG("name=%s", name); ++ ++ for(i = 0; i < NUM_SENV; i++) ++ { ++ if(SENV[i].name != NULL && !strcmp(SENV[i].name, name)) { ++ return &SENV[i]; ++ } ++ } ++ ++ return NULL; ++} ++ ++static server_env_t* find_matching_senv(server_env_t* senv) { ++ int i; ++ ++ _DBG("name=%s uid=%d gid=%d chroot=%s", senv->name, senv->uid, senv->gid, senv->chroot); + + for(i = 0; i < NUM_SENV; i++) +- { +- if(SENV[i].uid == uid && SENV[i].gid == gid && +- (SENV[i].chroot == NULL || !strcmp(SENV[i].chroot, chroot))) + { +- _DBG("Found existing senv: %i", i); +- return &SENV[i]; ++ if((senv->name != NULL && SENV[i].name != NULL && !strcmp(SENV[i].name, senv->name)) || ++ (senv->name == NULL && SENV[i].uid == senv->uid && SENV[i].gid == senv->gid && ++ ( ++ (SENV[i].chroot == NULL && senv->chroot == NULL) || ++ ((SENV[i].chroot != NULL || senv->chroot != NULL) && !strcmp(SENV[i].chroot, senv->chroot))) ++ ) ++ ) { ++ return &SENV[i]; ++ } + } ++ ++ return NULL; ++} ++ ++static server_env_t* senv_add(server_env_t *senv) ++{ ++ int socks[2]; ++ server_env_t *old_senv; ++ ++ _DBG("Searching for matching senv..."); ++ ++ old_senv = find_matching_senv(senv); ++ ++ if (old_senv) { ++ _DBG("Found existing senv"); ++ senv = old_senv; ++ return old_senv; + } + + if(NUM_SENV >= server_limit) +- { +- _DBG("server_limit reached!"); +- return NULL; +- } ++ { ++ _DBG("server_limit reached!"); ++ return NULL; ++ } + + _DBG("Creating new senv"); + +- SENV[NUM_SENV].uid = uid; +- SENV[NUM_SENV].gid = gid; +- SENV[NUM_SENV].chroot = chroot; +- +- SENV[NUM_SENV].min_processors = ap_min_processors; +- SENV[NUM_SENV].min_free_processors = ap_min_free_processors; +- SENV[NUM_SENV].max_processors = ap_max_processors; ++ memcpy(&SENV[NUM_SENV], senv, sizeof(server_env_t)); ++ ++ SENV[NUM_SENV].availability = 100; + + socketpair(PF_UNIX, SOCK_STREAM, 0, socks); + SENV[NUM_SENV].input = socks[0]; + SENV[NUM_SENV].output = socks[1]; + ++ senv = &SENV[NUM_SENV]; + return &SENV[server_env_image->control->num++]; + } + ++ + static const char* child_clone() + { + int i; +@@ -1869,7 +2065,14 @@ + new = &CHILD_INFO_TABLE[i]; + + new->senv = this->senv; +- new->type = CHILD_TYPE_WORKER; ++ ++ if (this->type == CHILD_TYPE_MULTIPLEXER) { ++ new->type = CHILD_TYPE_MULTIPLEXER; ++ } ++ else { ++ new->type = CHILD_TYPE_WORKER; ++ } ++ + new->sock_fd = this->sock_fd; + new->status = CHILD_STATUS_STARTING; + +@@ -1878,7 +2081,7 @@ + } + + static const char* child_add(int type, int status, +- apr_pool_t *pool, uid_t uid, gid_t gid, const char* chroot) ++ apr_pool_t *pool, server_env_t *senv) + { + _DBG("adding child #%d", NUM_CHILDS); + +@@ -1888,10 +2091,10 @@ + "Increase NumServers in your config file."; + } + +- if (chroot && !ap_is_directory(pool, chroot)) +- return apr_psprintf(pool, "Error: chroot directory [%s] does not exist", chroot); ++ if (senv->chroot && !ap_is_directory(pool, senv->chroot)) ++ return apr_psprintf(pool, "Error: chroot directory [%s] does not exist", senv->chroot); + +- CHILD_INFO_TABLE[NUM_CHILDS].senv = senv_add(uid, gid, chroot); ++ CHILD_INFO_TABLE[NUM_CHILDS].senv = senv_add(senv); + + if(CHILD_INFO_TABLE[NUM_CHILDS].senv == NULL) + { +@@ -1907,10 +2110,10 @@ + CHILD_INFO_TABLE[NUM_CHILDS].status = status; + + _DBG("[%d] uid=%d gid=%d type=%d chroot=%s", +- NUM_CHILDS, uid, gid, type, +- chroot); ++ NUM_CHILDS, senv->uid, senv->gid, type, ++ senv->chroot); + +- if (uid == 0 || gid == 0) ++ if (senv->uid == 0 || senv->gid == 0) + { + _DBG("Assigning root user/group to a child.", 0); + } +@@ -1957,7 +2160,7 @@ + (void) ap_update_child_status_from_indexes(slot, 0, SERVER_STARTING, + (request_rec *) NULL); + +- CHILD_INFO_TABLE[slot].status = CHILD_STATUS_ACTIVE; ++ CHILD_INFO_TABLE[slot].status = CHILD_STATUS_READY; + + + #ifdef _OSD_POSIX +@@ -2062,19 +2265,31 @@ + if(CHILD_INFO_TABLE[i].status == CHILD_STATUS_STARTING) + make_child(ap_server_conf, i); + } +- else if(((CHILD_INFO_TABLE[i].type == CHILD_TYPE_PROCESSOR || +- CHILD_INFO_TABLE[i].type == CHILD_TYPE_WORKER) && +- ap_scoreboard_image->parent[i].pid > 1) && +- (idle_processors (i) > 1 || total_processes (i) == 1) && ( +- (expire_timeout > 0 && ap_scoreboard_image->servers[i][0].status != SERVER_DEAD && +- apr_time_sec(now - ap_scoreboard_image->servers[i][0].last_used) > expire_timeout) || +- (idle_timeout > 0 && ap_scoreboard_image->servers[i][0].status == SERVER_READY && +- apr_time_sec(now - ap_scoreboard_image->servers[i][0].last_used) > idle_timeout))) ++ else if( ++ (((CHILD_INFO_TABLE[i].type == CHILD_TYPE_PROCESSOR || ++ CHILD_INFO_TABLE[i].type == CHILD_TYPE_WORKER) && ++ ap_scoreboard_image->parent[i].pid > 1) && ++ (idle_processors (i) > CHILD_INFO_TABLE[i].senv->min_free_processors || CHILD_INFO_TABLE[i].senv->min_free_processors == 0) && ++ total_processes (i) > CHILD_INFO_TABLE[i].senv->min_processors && ++ ( ++ (expire_timeout > 0 && ap_scoreboard_image->servers[i][0].status != SERVER_DEAD && ++ apr_time_sec(now - ap_scoreboard_image->servers[i][0].last_used) > expire_timeout) || ++ (idle_timeout > 0 && ap_scoreboard_image->servers[i][0].status == SERVER_READY && ++ apr_time_sec(now - ap_scoreboard_image->servers[i][0].last_used) > idle_timeout) || ++ (CHILD_INFO_TABLE[i].senv->max_free_processors > 0 && CHILD_INFO_TABLE[i].status == CHILD_STATUS_READY && ++ idle_processors(i) > CHILD_INFO_TABLE[i].senv->max_free_processors)) ++ ) ++ || (CHILD_INFO_TABLE[i].type == CHILD_TYPE_MULTIPLEXER && ++ (multiplexer_idle_timeout > 0 && ap_scoreboard_image->servers[i][0].status == SERVER_READY && ++ apr_time_sec(now - ap_scoreboard_image->servers[i][0].last_used) > multiplexer_idle_timeout) && ++ total_processors(i) > CHILD_INFO_TABLE[i].senv->min_processors ++ ) ++ ) + { + CHILD_INFO_TABLE[i].pid = 0; + CHILD_INFO_TABLE[i].status = CHILD_STATUS_STANDBY; + +- if(CHILD_INFO_TABLE[i].type == CHILD_TYPE_WORKER) ++ if(CHILD_INFO_TABLE[i].type == CHILD_TYPE_WORKER || CHILD_INFO_TABLE[i].type == CHILD_TYPE_MULTIPLEXER) + { + /* completely free up this slot */ + +@@ -2173,7 +2388,6 @@ + return 1; + } + +-#if 0 + #if APR_USE_SYSVSEM_SERIALIZE + if (ap_accept_lock_mech == APR_LOCK_DEFAULT || + ap_accept_lock_mech == APR_LOCK_SYSVSEM) { +@@ -2189,7 +2403,6 @@ + return 1; + } + } +-#endif + + if (!is_graceful) { + if (ap_run_pre_mpm(s->process->pool, SB_SHARED) != OK) { +@@ -2598,7 +2811,10 @@ + ap_listen_pre_config(); + ap_min_processors = DEFAULT_MIN_PROCESSORS; + ap_min_free_processors = DEFAULT_MIN_FREE_PROCESSORS; ++ ap_max_free_processors = DEFAULT_MAX_FREE_PROCESSORS; + ap_max_processors = DEFAULT_MAX_PROCESSORS; ++ ap_min_multiplexers = DEFAULT_MIN_MULTIPLEXERS; ++ ap_max_multiplexers = DEFAULT_MAX_MULTIPLEXERS; + ap_daemons_limit = server_limit; + ap_pid_fname = DEFAULT_PIDLOG; + ap_lock_fname = DEFAULT_LOCKFILE; +@@ -2608,6 +2824,13 @@ + ap_max_mem_free = APR_ALLOCATOR_MAX_FREE_UNLIMITED; + #endif + ++ expire_timeout = DEFAULT_EXPIRE_TIMEOUT; ++ idle_timeout = DEFAULT_IDLE_TIMEOUT; ++ multiplexer_idle_timeout = DEFAULT_MULTIPLEXER_IDLE_TIMEOUT; ++ processor_wait_timeout = DEFAULT_PROCESSOR_WAIT_TIMEOUT; ++ processor_wait_steps = DEFAULT_PROCESSOR_WAIT_STEPS; ++ ++ + apr_cpystrn(ap_coredump_dir, ap_server_root, sizeof(ap_coredump_dir)); + + /* we need to know ServerLimit and ThreadLimit before we start processing +@@ -2709,11 +2932,13 @@ + server_env_image->control = (server_env_control*)shmem; + shmem += sizeof(server_env_control*); + server_env_image->table = (server_env_t*)shmem; ++ } + ++ if(restart_num <= 2) { ++ _DBG("Cleaning server environments table"); ++ + server_env_image->control->num = 0; +- +- for (i = 0; i < tmp_server_limit; i++) +- { ++ for (i = 0; i < tmp_server_limit; i++) { + SENV[i].processor_id = -1; + SENV[i].uid = -1; + SENV[i].gid = -1; +@@ -2781,8 +3006,8 @@ + if (pass_request(r, processor) == -1) + { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, +- ap_server_conf, "Could not pass request to proper " "child, request will not be honoured."); +- return DECLINED; ++ ap_server_conf, "Could not pass request to processor %s (virtualhost %s), request will not be honoured.", ++ processor->senv->name, r->hostname); + } + _DBG("doing longjmp",0); + longjmp(CHILD_INFO_TABLE[my_child_num].jmpbuffer, 1); +@@ -2859,32 +3084,37 @@ + ap_rputs("
\n", r); + ap_rputs("

peruser status

\n", r); + ap_rputs("\n", r); +- ap_rputs("" +- "" ++ ap_rputs("" ++ "" + "" + "" +- "\n", r); ++ "" ++ "" ++ "\n", r); + for (x = 0; x < NUM_CHILDS; x++) + { + senv = CHILD_INFO_TABLE[x].senv; +- ap_rprintf(r, "" +- "" ++ ap_rprintf(r, "" ++ "" + "" +- "\n", ++ "\n", + CHILD_INFO_TABLE[x].id, + CHILD_INFO_TABLE[x].pid, + child_status_string(CHILD_INFO_TABLE[x].status), ++ scoreboard_status_string(SCOREBOARD_STATUS(x)), + child_type_string(CHILD_INFO_TABLE[x].type), + senv == NULL ? -1 : senv->uid, + senv == NULL ? -1 : senv->gid, + senv == NULL ? NULL : senv->chroot, ++ senv == NULL ? 0 : senv->nice_lvl, + senv == NULL ? -1 : CHILD_INFO_TABLE[x].senv->input, + senv == NULL ? -1 : CHILD_INFO_TABLE[x].senv->output, + CHILD_INFO_TABLE[x].sock_fd, + total_processors(x), + senv == NULL ? -1 : CHILD_INFO_TABLE[x].senv->max_processors, + idle_processors(x), +- senv == NULL ? -1 : CHILD_INFO_TABLE[x].senv->min_free_processors ++ senv == NULL ? -1 : CHILD_INFO_TABLE[x].senv->min_free_processors, ++ senv == NULL ? -1 : CHILD_INFO_TABLE[x].senv->availability + ); + } + ap_rputs("
IDPIDSTATUSTYPEUIDGIDCHROOTINPUT
IDPIDSTATUSSB STATUSTYPEUIDGIDCHROOTNICEINPUTOUTPUTSOCK_FDTOTAL PROCESSORSMAX PROCESSORSIDLE PROCESSORSMIN FREE PROCESSORS
IDLE PROCESSORSMIN FREE PROCESSORSAVAIL
%3d%5d%8s%12s%4d%4d%25s%5d
%3d%5d%8s%8s%12s%4d%4d%25s%3d%5d%6d%7d%d%d%d%d
%d%d%3d
\n", r); +@@ -2938,50 +3168,183 @@ + APR_OPTIONAL_HOOK(ap, status_hook, peruser_status_hook, NULL, NULL, APR_HOOK_MIDDLE); + } + +-/* we define an Processor w/ specific uid/gid */ +-static const char *cf_Processor(cmd_parms *cmd, void *dummy, +- const char *user_name, const char *group_name, const char *chroot) ++static const char *cf_Processor(cmd_parms *cmd, void *dummy, const char *arg) + { +- uid_t uid = ap_uname2id(user_name); +- gid_t gid = ap_gname2id(group_name); ++ const char *user_name = NULL, *group_name = NULL, *directive; ++ server_env_t senv; ++ ap_directive_t *current; ++ ++ const char *endp = ap_strrchr_c(arg, '>'); ++ ++ if (endp == NULL) { ++ return apr_psprintf(cmd->temp_pool, ++ "Error: Directive %s> missing closing '>'", cmd->cmd->name); ++ } ++ ++ arg = apr_pstrndup(cmd->pool, arg, endp - arg); ++ ++ if (!arg) { ++ return apr_psprintf(cmd->temp_pool, ++ "Error: %s> must specify a processor name", cmd->cmd->name); ++ } ++ ++ senv.name = ap_getword_conf(cmd->pool, &arg); ++ _DBG("processor_name: %s", senv.name); ++ ++ if (strlen(senv.name) == 0) { ++ return apr_psprintf(cmd->temp_pool, ++ "Error: Directive %s> takes one argument", cmd->cmd->name); ++ } ++ ++ /* Check for existing processors on first launch and between gracefuls */ ++ if (restart_num == 1 || is_graceful) { ++ server_env_t *old_senv = find_senv_by_name(senv.name); ++ ++ if (old_senv) { ++ return apr_psprintf(cmd->temp_pool, ++ "Error: Processor %s already defined", senv.name); ++ } ++ } ++ ++ senv.nice_lvl = 0; ++ senv.chroot = NULL; ++ senv.cgroup = NULL; ++ senv.min_processors = ap_min_processors; ++ senv.min_free_processors = ap_min_free_processors; ++ senv.max_free_processors = ap_max_free_processors; ++ senv.max_processors = ap_max_processors; ++ ++ current = cmd->directive->first_child; ++ ++ int proc_temp = 0; ++ for(; current != NULL; current = current->next) { ++ directive = current->directive; ++ ++ if (!strcasecmp(directive, "user")) { ++ user_name = current->args; ++ } ++ else if (!strcasecmp(directive, "group")) { ++ group_name = current->args; ++ } ++ else if (!strcasecmp(directive, "chroot")) { ++ senv.chroot = ap_getword_conf(cmd->pool, ¤t->args); ++ } ++ else if (!strcasecmp(directive, "nicelevel")) { ++ senv.nice_lvl = atoi(current->args); ++ } ++ else if (!strcasecmp(directive, "maxprocessors")) { ++ proc_temp = atoi(current->args); ++ ++ if (proc_temp < 1) { ++ ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, ++ "WARNING: Require MaxProcessors > 0, setting to 1"); ++ proc_temp = 1; ++ } ++ ++ senv.max_processors = proc_temp; ++ } ++ else if (!strcasecmp(directive, "minprocessors")) { ++ proc_temp = atoi(current->args); ++ ++ if (proc_temp < 0) { ++ ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, ++ "WARNING: Require MinProcessors >= 0, setting to 0"); ++ proc_temp = 0; ++ } ++ ++ senv.min_processors = proc_temp; ++ } ++ else if (!strcasecmp(directive, "minspareprocessors")) { ++ proc_temp = atoi(current->args); + +- _DBG("user=%s:%d group=%s:%d chroot=%s", +- user_name, uid, group_name, gid, chroot); ++ if (proc_temp < 0) { ++ ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, ++ "WARNING: Require MinSpareProcessors >= 0, setting to 0"); ++ proc_temp = 0; ++ } ++ ++ senv.min_free_processors = proc_temp; ++ } ++ else if (!strcasecmp(directive, "maxspareprocessors")) { ++ proc_temp = atoi(current->args); ++ ++ if (proc_temp < 0) { ++ ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, ++ "WARNING: Require MaxSpareProcessors >= 0, setting to 0"); ++ proc_temp = 0; ++ } ++ ++ senv.max_free_processors = proc_temp; ++ } ++ else if (!strcasecmp(directive, "cgroup")) { ++ senv.cgroup = ap_getword_conf(cmd->pool, ¤t->args); ++ } ++ else { ++ ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, ++ "Unknown directive %s in %s>", directive, cmd->cmd->name); ++ } ++ } ++ ++ if (user_name == NULL || group_name == NULL) { ++ return apr_psprintf(cmd->temp_pool, ++ "Error: User or Group must be set in %s>", cmd->cmd->name); ++ } ++ ++ senv.uid = ap_uname2id(user_name); ++ senv.gid = ap_gname2id(group_name); ++ ++ _DBG("name=%s user=%s:%d group=%s:%d chroot=%s nice_lvl=%d", ++ senv.name, user_name, senv.uid, group_name, senv.gid, senv.chroot, senv.nice_lvl); ++ ++ _DBG("min_processors=%d min_free_processors=%d max_spare_processors=%d max_processors=%d", ++ senv.min_processors, senv.min_free_processors, senv.max_free_processors, senv.max_processors); + + return child_add(CHILD_TYPE_PROCESSOR, CHILD_STATUS_STANDBY, +- cmd->pool, uid, gid, chroot); ++ cmd->pool, &senv); + } + + /* we define an Multiplexer child w/ specific uid/gid */ + static const char *cf_Multiplexer(cmd_parms *cmd, void *dummy, + const char *user_name, const char *group_name, const char *chroot) + { +- uid_t uid = ap_uname2id(user_name); +- gid_t gid = ap_gname2id(group_name); ++ server_env_t senv; ++ ++ senv.name = NULL; ++ ++ senv.uid = ap_uname2id(user_name); ++ senv.gid = ap_gname2id(group_name); ++ senv.nice_lvl = 0; ++ senv.cgroup = NULL; ++ senv.chroot = chroot; ++ ++ senv.min_processors = ap_min_multiplexers; ++ senv.min_free_processors = ap_min_free_processors; ++ senv.max_free_processors = ap_max_free_processors; ++ senv.max_processors = ap_max_multiplexers; + + _DBG("user=%s:%d group=%s:%d chroot=%s [multiplexer id %d]", +- user_name, uid, group_name, gid, chroot, NUM_CHILDS); ++ user_name, senv.uid, group_name, senv.gid, senv.chroot, NUM_CHILDS); + + return child_add(CHILD_TYPE_MULTIPLEXER, CHILD_STATUS_STARTING, +- cmd->pool, uid, gid, chroot); ++ cmd->pool, &senv); + } + + static const char* cf_ServerEnvironment(cmd_parms *cmd, void *dummy, +- const char *user_name, const char *group_name, const char *chroot) ++ const char *name) + { +- int uid = ap_uname2id(user_name); +- int gid = ap_gname2id(group_name); + peruser_server_conf *sconf = PERUSER_SERVER_CONF(cmd->server->module_config); + + _DBG("function entered", 0); + +- if (chroot && !ap_is_directory(cmd->pool, chroot)) +- return apr_psprintf(cmd->pool, "Error: chroot directory [%s] does not exist", chroot); ++ sconf->senv = find_senv_by_name(name); + +- sconf->senv = senv_add(uid, gid, chroot); ++ if (sconf->senv == NULL) { ++ return apr_psprintf(cmd->pool, ++ "Error: Processor %s not defined", name); ++ } + +- _DBG("user=%s:%d group=%s:%d chroot=%s numchilds=%d", +- user_name, uid, group_name, gid, chroot, NUM_CHILDS); ++ _DBG("user=%d group=%d chroot=%s numchilds=%d", ++ sconf->senv->uid, sconf->senv->gid, sconf->senv->chroot, NUM_CHILDS); + + return NULL; + } +@@ -3046,10 +3409,10 @@ + + min_procs = atoi(arg); + +- if (min_procs < 1) { ++ if (min_procs < 0) { + ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, +- "WARNING: Require MaxProcessors > 0, setting to 1"); +- min_procs = 1; ++ "WARNING: Require MinProcessors >= 0, setting to 0"); ++ min_procs = 0; + } + + if (ap_check_cmd_context(cmd, NOT_IN_VIRTUALHOST) != NULL) { +@@ -3075,10 +3438,10 @@ + + min_free_procs = atoi(arg); + +- if (min_free_procs < 1) { ++ if (min_free_procs < 0) { + ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, +- "WARNING: Require MinSpareProcessors > 0, setting to 1"); +- min_free_procs = 1; ++ "WARNING: Require MinSpareProcessors >= 0, setting to 0"); ++ min_free_procs = 0; + } + + if (ap_check_cmd_context(cmd, NOT_IN_VIRTUALHOST) != NULL) { +@@ -3092,6 +3455,35 @@ + return NULL; + } + ++static const char *set_max_free_processors (cmd_parms *cmd, void *dummy, const char *arg) ++{ ++ peruser_server_conf *sconf; ++ int max_free_procs; ++ const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT); ++ ++ if (err != NULL) { ++ return err; ++ } ++ ++ max_free_procs = atoi(arg); ++ ++ if (max_free_procs < 0) { ++ ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, ++ "WARNING: Require MaxSpareProcessors >= 0, setting to 0"); ++ max_free_procs = 0; ++ } ++ ++ if (ap_check_cmd_context(cmd, NOT_IN_VIRTUALHOST) != NULL) { ++ sconf = PERUSER_SERVER_CONF(cmd->server->module_config); ++ sconf->senv->max_free_processors = max_free_procs; ++ } ++ else { ++ ap_max_free_processors = max_free_procs; ++ } ++ ++ return NULL; ++} ++ + static const char *set_max_processors (cmd_parms *cmd, void *dummy, const char *arg) + { + peruser_server_conf *sconf; +@@ -3121,6 +3513,50 @@ + return NULL; + } + ++static const char *set_min_multiplexers (cmd_parms *cmd, void *dummy, const char *arg) ++{ ++ int min_multiplexers; ++ const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT); ++ ++ if (err != NULL) { ++ return err; ++ } ++ ++ min_multiplexers = atoi(arg); ++ ++ if (min_multiplexers < 1) { ++ ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, ++ "WARNING: Require MinMultiplexers > 0, setting to 1"); ++ min_multiplexers = 1; ++ } ++ ++ ap_min_multiplexers = min_multiplexers; ++ ++ return NULL; ++} ++ ++static const char *set_max_multiplexers (cmd_parms *cmd, void *dummy, const char *arg) ++{ ++ int max_multiplexers; ++ const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT); ++ ++ if (err != NULL) { ++ return err; ++ } ++ ++ max_multiplexers = atoi(arg); ++ ++ if (max_multiplexers < 1) { ++ ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, ++ "WARNING: Require MaxMultiplexers > 0, setting to 1"); ++ max_multiplexers = 1; ++ } ++ ++ ap_max_multiplexers = max_multiplexers; ++ ++ return NULL; ++} ++ + static const char *set_server_limit (cmd_parms *cmd, void *dummy, const char *arg) + { + int tmp_server_limit; +@@ -3183,6 +3619,42 @@ + return NULL; + } + ++static const char *set_multiplexer_idle_timeout (cmd_parms *cmd, void *dummy, const char *arg) { ++ const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); ++ ++ if (err != NULL) { ++ return err; ++ } ++ ++ multiplexer_idle_timeout = atoi(arg); ++ ++ return NULL; ++} ++ ++static const char *set_processor_wait_timeout (cmd_parms *cmd, void *dummy, const char *timeout, const char *steps) { ++ const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); ++ ++ if (err != NULL) { ++ return err; ++ } ++ ++ processor_wait_timeout = atoi(timeout); ++ ++ if (steps != NULL) { ++ int steps_tmp = atoi(steps); ++ ++ if (steps_tmp < 1) { ++ ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, ++ "WARNING: Require ProcessorWaitTimeout steps > 0, setting to 1"); ++ steps_tmp = 1; ++ } ++ ++ processor_wait_steps = steps_tmp; ++ } ++ ++ return NULL; ++} ++ + static const command_rec peruser_cmds[] = { + UNIX_DAEMON_COMMANDS, + LISTEN_COMMANDS, +@@ -3190,23 +3662,33 @@ + "Minimum number of idle children, to handle request spikes"), + AP_INIT_TAKE1("MinSpareServers", set_min_free_servers, NULL, RSRC_CONF, + "Minimum number of idle children, to handle request spikes"), ++AP_INIT_TAKE1("MaxSpareProcessors", set_max_free_processors, NULL, RSRC_CONF, ++ "Maximum number of idle children, 0 to disable"), + AP_INIT_TAKE1("MaxClients", set_max_clients, NULL, RSRC_CONF, + "Maximum number of children alive at the same time"), + AP_INIT_TAKE1("MinProcessors", set_min_processors, NULL, RSRC_CONF, + "Minimum number of processors per vhost"), + AP_INIT_TAKE1("MaxProcessors", set_max_processors, NULL, RSRC_CONF, + "Maximum number of processors per vhost"), ++AP_INIT_TAKE1("MinMultiplexers", set_min_multiplexers, NULL, RSRC_CONF, ++ "Minimum number of multiplexers the server can have"), ++AP_INIT_TAKE1("MaxMultiplexers", set_max_multiplexers, NULL, RSRC_CONF, ++ "Maximum number of multiplexers the server can have"), + AP_INIT_TAKE1("ServerLimit", set_server_limit, NULL, RSRC_CONF, + "Maximum value of MaxClients for this run of Apache"), + AP_INIT_TAKE1("ExpireTimeout", set_expire_timeout, NULL, RSRC_CONF, +- "Maximum idle time before a child is killed, 0 to disable"), ++ "Maximum time a child can live, 0 to disable"), + AP_INIT_TAKE1("IdleTimeout", set_idle_timeout, NULL, RSRC_CONF, + "Maximum time before a child is killed after being idle, 0 to disable"), ++AP_INIT_TAKE1("MultiplexerIdleTimeout", set_multiplexer_idle_timeout, NULL, RSRC_CONF, ++ "Maximum time before a multiplexer is killed after being idle, 0 to disable"), ++AP_INIT_TAKE12("ProcessorWaitTimeout", set_processor_wait_timeout, NULL, RSRC_CONF, ++ "Maximum time a multiplexer waits for the processor if it is busy"), + AP_INIT_TAKE23("Multiplexer", cf_Multiplexer, NULL, RSRC_CONF, + "Specify an Multiplexer Child configuration."), +-AP_INIT_TAKE23("Processor", cf_Processor, NULL, RSRC_CONF, +- "Specify a User and Group for a specific child process."), +-AP_INIT_TAKE23("ServerEnvironment", cf_ServerEnvironment, NULL, RSRC_CONF, ++AP_INIT_RAW_ARGS("Release-Note: >Audit-Trail: >Unformatted: