passenger 4.0.0.rc6 → 4.0.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of passenger might be problematic. Click here for more details.

Files changed (49) hide show
  1. data.tar.gz.asc +7 -7
  2. data/NEWS +14 -0
  3. data/build/basics.rb +2 -1
  4. data/build/packaging.rb +33 -0
  5. data/dev/run_travis.sh +1 -0
  6. data/doc/Architectural overview.html +1 -3
  7. data/doc/Packaging.txt.md +6 -6
  8. data/doc/Security of user switching support.html +1 -3
  9. data/doc/Users guide Apache.html +53 -20
  10. data/doc/Users guide Apache.idmap.txt +4 -0
  11. data/doc/Users guide Apache.txt +8 -0
  12. data/doc/Users guide Nginx.html +41 -18
  13. data/doc/Users guide Standalone.html +1 -3
  14. data/doc/users_guide_snippets/analysis_and_system_maintenance.txt +11 -5
  15. data/doc/users_guide_snippets/installation.txt +5 -1
  16. data/doc/users_guide_snippets/tips.txt +10 -7
  17. data/doc/users_guide_snippets/under_the_hood/page_caching_support.txt +2 -2
  18. data/ext/apache2/Configuration.cpp +5 -6
  19. data/ext/apache2/Configuration.hpp +0 -4
  20. data/ext/common/ApplicationPool2/Group.h +25 -43
  21. data/ext/common/ApplicationPool2/Implementation.cpp +51 -32
  22. data/ext/common/ApplicationPool2/Pool.h +6 -7
  23. data/ext/common/ApplicationPool2/Process.h +61 -44
  24. data/ext/common/ApplicationPool2/Spawner.h +5 -0
  25. data/ext/common/BackgroundEventLoop.cpp +5 -11
  26. data/ext/common/Constants.h +1 -1
  27. data/ext/common/Utils.cpp +1 -1
  28. data/ext/common/agents/HelperAgent/AgentOptions.h +1 -1
  29. data/ext/common/agents/HelperAgent/RequestHandler.h +2 -0
  30. data/ext/common/agents/LoggingAgent/LoggingServer.h +4 -1
  31. data/ext/common/agents/LoggingAgent/RemoteSender.h +58 -6
  32. data/lib/phusion_passenger.rb +2 -2
  33. data/lib/phusion_passenger/loader_shared_helpers.rb +6 -6
  34. data/lib/phusion_passenger/platform_info/compiler.rb +16 -0
  35. data/lib/phusion_passenger/platform_info/depcheck_specs/apache2.rb +1 -1
  36. data/lib/phusion_passenger/request_handler.rb +1 -0
  37. data/lib/phusion_passenger/standalone/start_command.rb +0 -4
  38. data/lib/phusion_passenger/utils/robust_interruption.rb +47 -28
  39. data/resources/templates/standalone/config.erb +4 -22
  40. data/test/config.json.example +1 -1
  41. data/test/cxx/ApplicationPool2/DirectSpawnerTest.cpp +5 -3
  42. data/test/cxx/ApplicationPool2/PoolTest.cpp +75 -2
  43. data/test/cxx/ApplicationPool2/SmartSpawnerTest.cpp +12 -7
  44. data/test/cxx/ApplicationPool2/SpawnerTestCases.cpp +18 -5
  45. data/test/cxx/RequestHandlerTest.cpp +3 -0
  46. data/test/ruby/shared/loader_sharedspec.rb +4 -0
  47. metadata +5 -6
  48. metadata.gz.asc +7 -7
  49. data/doc/Users guide Apache.index.sqlite3 +0 -0
@@ -1197,9 +1197,7 @@ use the <span class="monospaced">-p</span> option, e.g.:</p></div>
1197
1197
  </div>
1198
1198
  <div id="footnotes"><hr></div>
1199
1199
  <div id="footer">
1200
- <div id="footer-text">
1201
- Last updated 2013-03-06 12:16:21 CET
1202
- </div>
1200
+
1203
1201
  </div>
1204
1202
  <script>/*! jQuery v1.7.1 jquery.com | jquery.org/license */
1205
1203
  (function(a,b){function cy(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cv(a){if(!ck[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){cl||(cl=c.createElement("iframe"),cl.frameBorder=cl.width=cl.height=0),b.appendChild(cl);if(!cm||!cl.createElement)cm=(cl.contentWindow||cl.contentDocument).document,cm.write((c.compatMode==="CSS1Compat"?"<!doctype html>":"")+"<html><body>"),cm.close();d=cm.createElement(a),cm.body.appendChild(d),e=f.css(d,"display"),b.removeChild(cl)}ck[a]=e}return ck[a]}function cu(a,b){var c={};f.each(cq.concat.apply([],cq.slice(0,b)),function(){c[this]=a});return c}function ct(){cr=b}function cs(){setTimeout(ct,0);return cr=f.now()}function cj(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ci(){try{return new a.XMLHttpRequest}catch(b){}}function cc(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g<i;g++){if(g===1)for(h in a.converters)typeof h=="string"&&(e[h.toLowerCase()]=a.converters[h]);l=k,k=d[g];if(k==="*")k=l;else if(l!=="*"&&l!==k){m=l+" "+k,n=e[m]||e["* "+k];if(!n){p=b;for(o in e){j=o.split(" ");if(j[0]===l||j[0]==="*"){p=e[j[1]+" "+k];if(p){o=e[o],o===!0?n=p:p===!0&&(n=o);break}}}}!n&&!p&&f.error("No conversion from "+m.replace(" "," to ")),n!==!0&&(c=n?n(c):p(o(c)))}}return c}function cb(a,c,d){var e=a.contents,f=a.dataTypes,g=a.responseFields,h,i,j,k;for(i in g)i in d&&(c[g[i]]=d[i]);while(f[0]==="*")f.shift(),h===b&&(h=a.mimeType||c.getResponseHeader("content-type"));if(h)for(i in e)if(e[i]&&e[i].test(h)){f.unshift(i);break}if(f[0]in d)j=f[0];else{for(i in d){if(!f[0]||a.converters[i+" "+f[0]]){j=i;break}k||(k=i)}j=j||k}if(j){j!==f[0]&&f.unshift(j);return d[j]}}function ca(a,b,c,d){if(f.isArray(b))f.each(b,function(b,e){c||bE.test(a)?d(a,e):ca(a+"["+(typeof e=="object"||f.isArray(e)?b:"")+"]",e,c,d)});else if(!c&&b!=null&&typeof b=="object")for(var e in b)ca(a+"["+e+"]",b[e],c,d);else d(a,b)}function b_(a,c){var d,e,g=f.ajaxSettings.flatOptions||{};for(d in c)c[d]!==b&&((g[d]?a:e||(e={}))[d]=c[d]);e&&f.extend(!0,a,e)}function b$(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h=a[f],i=0,j=h?h.length:0,k=a===bT,l;for(;i<j&&(k||!l);i++)l=h[i](c,d,e),typeof l=="string"&&(!k||g[l]?l=b:(c.dataTypes.unshift(l),l=b$(a,c,d,e,l,g)));(k||!l)&&!g["*"]&&(l=b$(a,c,d,e,"*",g));return l}function bZ(a){return function(b,c){typeof b!="string"&&(c=b,b="*");if(f.isFunction(c)){var d=b.toLowerCase().split(bP),e=0,g=d.length,h,i,j;for(;e<g;e++)h=d[e],j=/^\+/.test(h),j&&(h=h.substr(1)||"*"),i=a[h]=a[h]||[],i[j?"unshift":"push"](c)}}}function bC(a,b,c){var d=b==="width"?a.offsetWidth:a.offsetHeight,e=b==="width"?bx:by,g=0,h=e.length;if(d>0){if(c!=="border")for(;g<h;g++)c||(d-=parseFloat(f.css(a,"padding"+e[g]))||0),c==="margin"?d+=parseFloat(f.css(a,c+e[g]))||0:d-=parseFloat(f.css(a,"border"+e[g]+"Width"))||0;return d+"px"}d=bz(a,b,b);if(d<0||d==null)d=a.style[b]||0;d=parseFloat(d)||0;if(c)for(;g<h;g++)d+=parseFloat(f.css(a,"padding"+e[g]))||0,c!=="padding"&&(d+=parseFloat(f.css(a,"border"+e[g]+"Width"))||0),c==="margin"&&(d+=parseFloat(f.css(a,c+e[g]))||0);return d+"px"}function bp(a,b){b.src?f.ajax({url:b.src,async:!1,dataType:"script"}):f.globalEval((b.text||b.textContent||b.innerHTML||"").replace(bf,"/*$0*/")),b.parentNode&&b.parentNode.removeChild(b)}function bo(a){var b=c.createElement("div");bh.appendChild(b),b.innerHTML=a.outerHTML;return b.firstChild}function bn(a){var b=(a.nodeName||"").toLowerCase();b==="input"?bm(a):b!=="script"&&typeof a.getElementsByTagName!="undefined"&&f.grep(a.getElementsByTagName("input"),bm)}function bm(a){if(a.type==="checkbox"||a.type==="radio")a.defaultChecked=a.checked}function bl(a){return typeof a.getElementsByTagName!="undefined"?a.getElementsByTagName("*"):typeof a.querySelectorAll!="undefined"?a.querySelectorAll("*"):[]}function bk(a,b){var c;if(b.nodeType===1){b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase();if(c==="object")b.outerHTML=a.outerHTML;else if(c!=="input"||a.type!=="checkbox"&&a.type!=="radio"){if(c==="option")b.selected=a.defaultSelected;else if(c==="input"||c==="textarea")b.defaultValue=a.defaultValue}else a.checked&&(b.defaultChecked=b.checked=a.checked),b.value!==a.value&&(b.value=a.value);b.removeAttribute(f.expando)}}function bj(a,b){if(b.nodeType===1&&!!f.hasData(a)){var c,d,e,g=f._data(a),h=f._data(b,g),i=g.events;if(i){delete h.handle,h.events={};for(c in i)for(d=0,e=i[c].length;d<e;d++)f.event.add(b,c+(i[c][d].namespace?".":"")+i[c][d].namespace,i[c][d],i[c][d].data)}h.data&&(h.data=f.extend({},h.data))}}function bi(a,b){return f.nodeName(a,"table")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function U(a){var b=V.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function T(a,b,c){b=b||0;if(f.isFunction(b))return f.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return f.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=f.grep(a,function(a){return a.nodeType===1});if(O.test(b))return f.filter(b,d,!c);b=f.filter(b,d)}return f.grep(a,function(a,d){return f.inArray(a,b)>=0===c})}function S(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function K(){return!0}function J(){return!1}function n(a,b,c){var d=b+"defer",e=b+"queue",g=b+"mark",h=f._data(a,d);h&&(c==="queue"||!f._data(a,e))&&(c==="mark"||!f._data(a,g))&&setTimeout(function(){!f._data(a,e)&&!f._data(a,g)&&(f.removeData(a,d,!0),h.fire())},0)}function m(a){for(var b in a){if(b==="data"&&f.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function l(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(k,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNumeric(d)?parseFloat(d):j.test(d)?f.parseJSON(d):d}catch(g){}f.data(a,c,d)}else d=b}return d}function h(a){var b=g[a]={},c,d;a=a.split(/\s+/);for(c=0,d=a.length;c<d;c++)b[a[c]]=!0;return b}var c=a.document,d=a.navigator,e=a.location,f=function(){function J(){if(!e.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(J,1);return}e.ready()}}var e=function(a,b){return new e.fn.init(a,b,h)},f=a.jQuery,g=a.$,h,i=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,n=/^[\],:{}\s]*$/,o=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,p=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,q=/(?:^|:|,)(?:\s*\[)+/g,r=/(webkit)[ \/]([\w.]+)/,s=/(opera)(?:.*version)?[ \/]([\w.]+)/,t=/(msie) ([\w.]+)/,u=/(mozilla)(?:.*? rv:([\w.]+))?/,v=/-([a-z]|[0-9])/ig,w=/^-ms-/,x=function(a,b){return(b+"").toUpperCase()},y=d.userAgent,z,A,B,C=Object.prototype.toString,D=Object.prototype.hasOwnProperty,E=Array.prototype.push,F=Array.prototype.slice,G=String.prototype.trim,H=Array.prototype.indexOf,I={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=m.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.7.1",length:0,size:function(){return this.length},toArray:function(){return F.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?E.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),A.add(a);return this},eq:function(a){a=+a;return a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(F.apply(this,arguments),"slice",F.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:E,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j<k;j++)if((a=arguments[j])!=null)for(c in a){d=i[c],f=a[c];if(i===f)continue;l&&f&&(e.isPlainObject(f)||(g=e.isArray(f)))?(g?(g=!1,h=d&&e.isArray(d)?d:[]):h=d&&e.isPlainObject(d)?d:{},i[c]=e.extend(l,h,f)):f!==b&&(i[c]=f)}return i},e.extend({noConflict:function(b){a.$===e&&(a.$=g),b&&a.jQuery===e&&(a.jQuery=f);return e},isReady:!1,readyWait:1,holdReady:function(a){a?e.readyWait++:e.ready(!0)},ready:function(a){if(a===!0&&!--e.readyWait||a!==!0&&!e.isReady){if(!c.body)return setTimeout(e.ready,1);e.isReady=!0;if(a!==!0&&--e.readyWait>0)return;A.fireWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").off("ready")}},bindReady:function(){if(!A){A=e.Callbacks("once memory");if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",B,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",B),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&J()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a&&typeof a=="object"&&"setInterval"in a},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):I[C.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;try{if(a.constructor&&!D.call(a,"constructor")&&!D.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||D.call(a,d)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw new Error(a)},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(n.test(b.replace(o,"@").replace(p,"]").replace(q,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(c){var d,f;try{a.DOMParser?(f=new DOMParser,d=f.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(g){d=b}(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&e.error("Invalid XML: "+c);return d},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(w,"ms-").replace(v,x)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g<h;)if(c.apply(a[g++],d)===!1)break}else if(i){for(f in a)if(c.call(a[f],f,a[f])===!1)break}else for(;g<h;)if(c.call(a[g],g,a[g++])===!1)break;return a},trim:G?function(a){return a==null?"":G.call(a)}:function(a){return a==null?"":(a+"").replace(k,"").replace(l,"")},makeArray:function(a,b){var c=b||[];if(a!=null){var d=e.type(a);a.length==null||d==="string"||d==="function"||d==="regexp"||e.isWindow(a)?E.call(c,a):e.merge(c,a)}return c},inArray:function(a,b,c){var d;if(b){if(H)return H.call(b,a,c);d=b.length,c=c?c<0?Math.max(0,d+c):c:0;for(;c<d;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,c){var d=a.length,e=0;if(typeof c.length=="number")for(var f=c.length;e<f;e++)a[d++]=c[e];else while(c[e]!==b)a[d++]=c[e++];a.length=d;return a},grep:function(a,b,c){var d=[],e;c=!!c;for(var f=0,g=a.length;f<g;f++)e=!!b(a[f],f),c!==e&&d.push(a[f]);return d},map:function(a,c,d){var f,g,h=[],i=0,j=a.length,k=a instanceof e||j!==b&&typeof j=="number"&&(j>0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i<j;i++)f=c(a[i],i,d),f!=null&&(h[h.length]=f);else for(g in a)f=c(a[g],g,d),f!=null&&(h[h.length]=f);return h.concat.apply([],h)},guid:1,proxy:function(a,c){if(typeof c=="string"){var d=a[c];c=a,a=d}if(!e.isFunction(a))return b;var f=F.call(arguments,2),g=function(){return a.apply(c,f.concat(F.call(arguments)))};g.guid=a.guid=a.guid||g.guid||e.guid++;return g},access:function(a,c,d,f,g,h){var i=a.length;if(typeof c=="object"){for(var j in c)e.access(a,j,c[j],f,g,d);return a}if(d!==b){f=!h&&f&&e.isFunction(d);for(var k=0;k<i;k++)g(a[k],c,f?d.call(a[k],k,g(a[k],c)):d,h);return a}return i?g(a[0],c):b},now:function(){return(new Date).getTime()},uaMatch:function(a){a=a.toLowerCase();var b=r.exec(a)||s.exec(a)||t.exec(a)||a.indexOf("compatible")<0&&u.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},sub:function(){function a(b,c){return new a.fn.init(b,c)}e.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function(d,f){f&&f instanceof e&&!(f instanceof a)&&(f=a(f));return e.fn.init.call(this,d,f,b)},a.fn.init.prototype=a.fn;var b=a(c);return a},browser:{}}),e.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){I["[object "+b+"]"]=b.toLowerCase()}),z=e.uaMatch(y),z.browser&&(e.browser[z.browser]=!0,e.browser.version=z.version),e.browser.webkit&&(e.browser.safari=!0),j.test(" ")&&(k=/^[\s\xA0]+/,l=/[\s\xA0]+$/),h=e(c),c.addEventListener?B=function(){c.removeEventListener("DOMContentLoaded",B,!1),e.ready()}:c.attachEvent&&(B=function(){c.readyState==="complete"&&(c.detachEvent("onreadystatechange",B),e.ready())});return e}(),g={};f.Callbacks=function(a){a=a?g[a]||h(a):{};var c=[],d=[],e,i,j,k,l,m=function(b){var d,e,g,h,i;for(d=0,e=b.length;d<e;d++)g=b[d],h=f.type(g),h==="array"?m(g):h==="function"&&(!a.unique||!o.has(g))&&c.push(g)},n=function(b,f){f=f||[],e=!a.memory||[b,f],i=!0,l=j||0,j=0,k=c.length;for(;c&&l<k;l++)if(c[l].apply(b,f)===!1&&a.stopOnFalse){e=!0;break}i=!1,c&&(a.once?e===!0?o.disable():c=[]:d&&d.length&&(e=d.shift(),o.fireWith(e[0],e[1])))},o={add:function(){if(c){var a=c.length;m(arguments),i?k=c.length:e&&e!==!0&&(j=a,n(e[0],e[1]))}return this},remove:function(){if(c){var b=arguments,d=0,e=b.length;for(;d<e;d++)for(var f=0;f<c.length;f++)if(b[d]===c[f]){i&&f<=k&&(k--,f<=l&&l--),c.splice(f--,1);if(a.unique)break}}return this},has:function(a){if(c){var b=0,d=c.length;for(;b<d;b++)if(a===c[b])return!0}return!1},empty:function(){c=[];return this},disable:function(){c=d=e=b;return this},disabled:function(){return!c},lock:function(){d=b,(!e||e===!0)&&o.disable();return this},locked:function(){return!d},fireWith:function(b,c){d&&(i?a.once||d.push([b,c]):(!a.once||!e)&&n(b,c));return this},fire:function(){o.fireWith(this,arguments);return this},fired:function(){return!!e}};return o};var i=[].slice;f.extend({Deferred:function(a){var b=f.Callbacks("once memory"),c=f.Callbacks("once memory"),d=f.Callbacks("memory"),e="pending",g={resolve:b,reject:c,notify:d},h={done:b.add,fail:c.add,progress:d.add,state:function(){return e},isResolved:b.fired,isRejected:c.fired,then:function(a,b,c){i.done(a).fail(b).progress(c);return this},always:function(){i.done.apply(i,arguments).fail.apply(i,arguments);return this},pipe:function(a,b,c){return f.Deferred(function(d){f.each({done:[a,"resolve"],fail:[b,"reject"],progress:[c,"notify"]},function(a,b){var c=b[0],e=b[1],g;f.isFunction(c)?i[a](function(){g=c.apply(this,arguments),g&&f.isFunction(g.promise)?g.promise().then(d.resolve,d.reject,d.notify):d[e+"With"](this===i?d:this,[g])}):i[a](d[e])})}).promise()},promise:function(a){if(a==null)a=h;else for(var b in h)a[b]=h[b];return a}},i=h.promise({}),j;for(j in g)i[j]=g[j].fire,i[j+"With"]=g[j].fireWith;i.done(function(){e="resolved"},c.disable,d.lock).fail(function(){e="rejected"},b.disable,d.lock),a&&a.call(i,i);return i},when:function(a){function m(a){return function(b){e[a]=arguments.length>1?i.call(arguments,0):b,j.notifyWith(k,e)}}function l(a){return function(c){b[a]=arguments.length>1?i.call(arguments,0):c,--g||j.resolveWith(j,b)}}var b=i.call(arguments,0),c=0,d=b.length,e=Array(d),g=d,h=d,j=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred(),k=j.promise();if(d>1){for(;c<d;c++)b[c]&&b[c].promise&&f.isFunction(b[c].promise)?b[c].promise().then(l(c),j.reject,m(c)):--g;g||j.resolveWith(j,b)}else j!==a&&j.resolveWith(j,d?[a]:[]);return k}}),f.support=function(){var b,d,e,g,h,i,j,k,l,m,n,o,p,q=c.createElement("div"),r=c.documentElement;q.setAttribute("className","t"),q.innerHTML=" <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>",d=q.getElementsByTagName("*"),e=q.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=q.getElementsByTagName("input")[0],b={leadingWhitespace:q.firstChild.nodeType===3,tbody:!q.getElementsByTagName("tbody").length,htmlSerialize:!!q.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:q.className!=="t",enctype:!!c.createElement("form").enctype,html5Clone:c.createElement("nav").cloneNode(!0).outerHTML!=="<:nav></:nav>",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0},i.checked=!0,b.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,b.optDisabled=!h.disabled;try{delete q.test}catch(s){b.deleteExpando=!1}!q.addEventListener&&q.attachEvent&&q.fireEvent&&(q.attachEvent("onclick",function(){b.noCloneEvent=!1}),q.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),b.radioValue=i.value==="t",i.setAttribute("checked","checked"),q.appendChild(i),k=c.createDocumentFragment(),k.appendChild(q.lastChild),b.checkClone=k.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=i.checked,k.removeChild(i),k.appendChild(q),q.innerHTML="",a.getComputedStyle&&(j=c.createElement("div"),j.style.width="0",j.style.marginRight="0",q.style.width="2px",q.appendChild(j),b.reliableMarginRight=(parseInt((a.getComputedStyle(j,null)||{marginRight:0}).marginRight,10)||0)===0);if(q.attachEvent)for(o in{submit:1,change:1,focusin:1})n="on"+o,p=n in q,p||(q.setAttribute(n,"return;"),p=typeof q[n]=="function"),b[o+"Bubbles"]=p;k.removeChild(q),k=g=h=j=q=i=null,f(function(){var a,d,e,g,h,i,j,k,m,n,o,r=c.getElementsByTagName("body")[0];!r||(j=1,k="position:absolute;top:0;left:0;width:1px;height:1px;margin:0;",m="visibility:hidden;border:0;",n="style='"+k+"border:5px solid #000;padding:0;'",o="<div "+n+"><div></div></div>"+"<table "+n+" cellpadding='0' cellspacing='0'>"+"<tr><td></td></tr></table>",a=c.createElement("div"),a.style.cssText=m+"width:0;height:0;position:static;top:0;margin-top:"+j+"px",r.insertBefore(a,r.firstChild),q=c.createElement("div"),a.appendChild(q),q.innerHTML="<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>",l=q.getElementsByTagName("td"),p=l[0].offsetHeight===0,l[0].style.display="",l[1].style.display="none",b.reliableHiddenOffsets=p&&l[0].offsetHeight===0,q.innerHTML="",q.style.width=q.style.paddingLeft="1px",f.boxModel=b.boxModel=q.offsetWidth===2,typeof q.style.zoom!="undefined"&&(q.style.display="inline",q.style.zoom=1,b.inlineBlockNeedsLayout=q.offsetWidth===2,q.style.display="",q.innerHTML="<div style='width:4px;'></div>",b.shrinkWrapBlocks=q.offsetWidth!==2),q.style.cssText=k+m,q.innerHTML=o,d=q.firstChild,e=d.firstChild,h=d.nextSibling.firstChild.firstChild,i={doesNotAddBorder:e.offsetTop!==5,doesAddBorderForTableAndCells:h.offsetTop===5},e.style.position="fixed",e.style.top="20px",i.fixedPosition=e.offsetTop===20||e.offsetTop===15,e.style.position=e.style.top="",d.style.overflow="hidden",d.style.position="relative",i.subtractsBorderForOverflowNotVisible=e.offsetTop===-5,i.doesNotIncludeMarginInBodyOffset=r.offsetTop!==j,r.removeChild(a),q=a=null,f.extend(b,i))});return b}();var j=/^(?:\{.*\}|\[.*\])$/,k=/([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!m(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g,h,i,j=f.expando,k=typeof c=="string",l=a.nodeType,m=l?f.cache:a,n=l?a[j]:a[j]&&j,o=c==="events";if((!n||!m[n]||!o&&!e&&!m[n].data)&&k&&d===b)return;n||(l?a[j]=n=++f.uuid:n=j),m[n]||(m[n]={},l||(m[n].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?m[n]=f.extend(m[n],c):m[n].data=f.extend(m[n].data,c);g=h=m[n],e||(h.data||(h.data={}),h=h.data),d!==b&&(h[f.camelCase(c)]=d);if(o&&!h[c])return g.events;k?(i=h[c],i==null&&(i=h[f.camelCase(c)])):i=h;return i}},removeData:function(a,b,c){if(!!f.acceptData(a)){var d,e,g,h=f.expando,i=a.nodeType,j=i?f.cache:a,k=i?a[h]:h;if(!j[k])return;if(b){d=c?j[k]:j[k].data;if(d){f.isArray(b)||(b in d?b=[b]:(b=f.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,g=b.length;e<g;e++)delete d[b[e]];if(!(c?m:f.isEmptyObject)(d))return}}if(!c){delete j[k].data;if(!m(j[k]))return}f.support.deleteExpando||!j.setInterval?delete j[k]:j[k]=null,i&&(f.support.deleteExpando?delete a[h]:a.removeAttribute?a.removeAttribute(h):a[h]=null)}},_data:function(a,b,c){return f.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=f.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),f.fn.extend({data:function(a,c){var d,e,g,h=null;if(typeof a=="undefined"){if(this.length){h=f.data(this[0]);if(this[0].nodeType===1&&!f._data(this[0],"parsedAttrs")){e=this[0].attributes;for(var i=0,j=e.length;i<j;i++)g=e[i].name,g.indexOf("data-")===0&&(g=f.camelCase(g.substring(5)),l(this[0],g,h[g]));f._data(this[0],"parsedAttrs",!0)}}return h}if(typeof a=="object")return this.each(function(){f.data(this,a)});d=a.split("."),d[1]=d[1]?"."+d[1]:"";if(c===b){h=this.triggerHandler("getData"+d[1]+"!",[d[0]]),h===b&&this.length&&(h=f.data(this[0],a),h=l(this[0],a,h));return h===b&&d[1]?this.data(d[0]):h}return this.each(function(){var b=f(this),e=[d[0],c];b.triggerHandler("setData"+d[1]+"!",e),f.data(this,a,c),b.triggerHandler("changeData"+d[1]+"!",e)})},removeData:function(a){return this.each(function(){f.removeData(this,a)})}}),f.extend({_mark:function(a,b){a&&(b=(b||"fx")+"mark",f._data(a,b,(f._data(a,b)||0)+1))},_unmark:function(a,b,c){a!==!0&&(c=b,b=a,a=!1);if(b){c=c||"fx";var d=c+"mark",e=a?0:(f._data(b,d)||1)-1;e?f._data(b,d,e):(f.removeData(b,d,!0),n(b,c,"mark"))}},queue:function(a,b,c){var d;if(a){b=(b||"fx")+"queue",d=f._data(a,b),c&&(!d||f.isArray(c)?d=f._data(a,b,f.makeArray(c)):d.push(c));return d||[]}},dequeue:function(a,b){b=b||"fx";var c=f.queue(a,b),d=c.shift(),e={};d==="inprogress"&&(d=c.shift()),d&&(b==="fx"&&c.unshift("inprogress"),f._data(a,b+".run",e),d.call(a,function(){f.dequeue(a,b)},e)),c.length||(f.removeData(a,b+"queue "+b+".run",!0),n(a,b,"queue"))}}),f.fn.extend({queue:function(a,c){typeof a!="string"&&(c=a,a="fx");if(c===b)return f.queue(this[0],a);return this.each(function(){var b=f.queue(this,a,c);a==="fx"&&b[0]!=="inprogress"&&f.dequeue(this,a)})},dequeue:function(a){return this.each(function(){f.dequeue(this,a)})},delay:function(a,b){a=f.fx?f.fx.speeds[a]||a:a,b=b||"fx";return this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,c){function m(){--h||d.resolveWith(e,[e])}typeof a!="string"&&(c=a,a=b),a=a||"fx";var d=f.Deferred(),e=this,g=e.length,h=1,i=a+"defer",j=a+"queue",k=a+"mark",l;while(g--)if(l=f.data(e[g],i,b,!0)||(f.data(e[g],j,b,!0)||f.data(e[g],k,b,!0))&&f.data(e[g],i,f.Callbacks("once memory"),!0))h++,l.add(m);m();return d.promise()}});var o=/[\n\t\r]/g,p=/\s+/,q=/\r/g,r=/^(?:button|input)$/i,s=/^(?:button|input|object|select|textarea)$/i,t=/^a(?:rea)?$/i,u=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,v=f.support.getSetAttribute,w,x,y;f.fn.extend({attr:function(a,b){return f.access(this,a,b,!0,f.attr)},removeAttr:function(a){return this.each(function(){f.removeAttr(this,a)})},prop:function(a,b){return f.access(this,a,b,!0,f.prop)},removeProp:function(a){a=f.propFix[a]||a;return this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,g,h,i;if(f.isFunction(a))return this.each(function(b){f(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(p);for(c=0,d=this.length;c<d;c++){e=this[c];if(e.nodeType===1)if(!e.className&&b.length===1)e.className=a;else{g=" "+e.className+" ";for(h=0,i=b.length;h<i;h++)~g.indexOf(" "+b[h]+" ")||(g+=b[h]+" ");e.className=f.trim(g)}}}return this},removeClass:function(a){var c,d,e,g,h,i,j;if(f.isFunction(a))return this.each(function(b){f(this).removeClass(a.call(this,b,this.className))});if(a&&typeof a=="string"||a===b){c=(a||"").split(p);for(d=0,e=this.length;d<e;d++){g=this[d];if(g.nodeType===1&&g.className)if(a){h=(" "+g.className+" ").replace(o," ");for(i=0,j=c.length;i<j;i++)h=h.replace(" "+c[i]+" "," ");g.className=f.trim(h)}else g.className=""}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";if(f.isFunction(a))return this.each(function(c){f(this).toggleClass(a.call(this,c,this.className,b),b)});return this.each(function(){if(c==="string"){var e,g=0,h=f(this),i=b,j=a.split(p);while(e=j[g++])i=d?i:!h.hasClass(e),h[i?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&f._data(this,"__className__",this.className),this.className=this.className||a===!1?"":f._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ",c=0,d=this.length;for(;c<d;c++)if(this[c].nodeType===1&&(" "+this[c].className+" ").replace(o," ").indexOf(b)>-1)return!0;return!1},val:function(a){var c,d,e,g=this[0];{if(!!arguments.length){e=f.isFunction(a);return this.each(function(d){var g=f(this),h;if(this.nodeType===1){e?h=a.call(this,d,g.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.nodeName.toLowerCase()]||f.valHooks[this.type];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}if(g){c=f.valHooks[g.nodeName.toLowerCase()]||f.valHooks[g.type];if(c&&"get"in c&&(d=c.get(g,"value"))!==b)return d;d=g.value;return typeof d=="string"?d.replace(q,""):d==null?"":d}}}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,g=a.selectedIndex,h=[],i=a.options,j=a.type==="select-one";if(g<0)return null;c=j?g:0,d=j?g+1:i.length;for(;c<d;c++){e=i[c];if(e.selected&&(f.support.optDisabled?!e.disabled:e.getAttribute("disabled")===null)&&(!e.parentNode.disabled||!f.nodeName(e.parentNode,"optgroup"))){b=f(e).val();if(j)return b;h.push(b)}}if(j&&!h.length&&i.length)return f(i[g]).val();return h},set:function(a,b){var c=f.makeArray(b);f(a).find("option").each(function(){this.selected=f.inArray(f(this).val(),c)>=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attr:function(a,c,d,e){var g,h,i,j=a.nodeType;if(!!a&&j!==3&&j!==8&&j!==2){if(e&&c in f.attrFn)return f(a)[c](d);if(typeof a.getAttribute=="undefined")return f.prop(a,c,d);i=j!==1||!f.isXMLDoc(a),i&&(c=c.toLowerCase(),h=f.attrHooks[c]||(u.test(c)?x:w));if(d!==b){if(d===null){f.removeAttr(a,c);return}if(h&&"set"in h&&i&&(g=h.set(a,d,c))!==b)return g;a.setAttribute(c,""+d);return d}if(h&&"get"in h&&i&&(g=h.get(a,c))!==null)return g;g=a.getAttribute(c);return g===null?b:g}},removeAttr:function(a,b){var c,d,e,g,h=0;if(b&&a.nodeType===1){d=b.toLowerCase().split(p),g=d.length;for(;h<g;h++)e=d[h],e&&(c=f.propFix[e]||e,f.attr(a,e,""),a.removeAttribute(v?e:c),u.test(e)&&c in a&&(a[c]=!1))}},attrHooks:{type:{set:function(a,b){if(r.test(a.nodeName)&&a.parentNode)f.error("type property can't be changed");else if(!f.support.radioValue&&b==="radio"&&f.nodeName(a,"input")){var c=a.value;a.setAttribute("type",b),c&&(a.value=c);return b}}},value:{get:function(a,b){if(w&&f.nodeName(a,"button"))return w.get(a,b);return b in a?a.value:null},set:function(a,b,c){if(w&&f.nodeName(a,"button"))return w.set(a,b,c);a.value=b}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a,c,d){var e,g,h,i=a.nodeType;if(!!a&&i!==3&&i!==8&&i!==2){h=i!==1||!f.isXMLDoc(a),h&&(c=f.propFix[c]||c,g=f.propHooks[c]);return d!==b?g&&"set"in g&&(e=g.set(a,d,c))!==b?e:a[c]=d:g&&"get"in g&&(e=g.get(a,c))!==null?e:a[c]}},propHooks:{tabIndex:{get:function(a){var c=a.getAttributeNode("tabindex");return c&&c.specified?parseInt(c.value,10):s.test(a.nodeName)||t.test(a.nodeName)&&a.href?0:b}}}}),f.attrHooks.tabindex=f.propHooks.tabIndex,x={get:function(a,c){var d,e=f.prop(a,c);return e===!0||typeof e!="boolean"&&(d=a.getAttributeNode(c))&&d.nodeValue!==!1?c.toLowerCase():b},set:function(a,b,c){var d;b===!1?f.removeAttr(a,c):(d=f.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase()));return c}},v||(y={name:!0,id:!0},w=f.valHooks.button={get:function(a,c){var d;d=a.getAttributeNode(c);return d&&(y[c]?d.nodeValue!=="":d.specified)?d.nodeValue:b},set:function(a,b,d){var e=a.getAttributeNode(d);e||(e=c.createAttribute(d),a.setAttributeNode(e));return e.nodeValue=b+""}},f.attrHooks.tabindex.set=w.set,f.each(["width","height"],function(a,b){f.attrHooks[b]=f.extend(f.attrHooks[b],{set:function(a,c){if(c===""){a.setAttribute(b,"auto");return c}}})}),f.attrHooks.contenteditable={get:w.get,set:function(a,b,c){b===""&&(b="false"),w.set(a,b,c)}}),f.support.hrefNormalized||f.each(["href","src","width","height"],function(a,c){f.attrHooks[c]=f.extend(f.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),f.support.style||(f.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=""+b}}),f.support.optSelected||(f.propHooks.selected=f.extend(f.propHooks.selected,{get:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex);return null}})),f.support.enctype||(f.propFix.enctype="encoding"),f.support.checkOn||f.each(["radio","checkbox"],function(){f.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),f.each(["radio","checkbox"],function(){f.valHooks[this]=f.extend(f.valHooks[this],{set:function(a,b){if(f.isArray(b))return a.checked=f.inArray(f(a).val(),b)>=0}})});var z=/^(?:textarea|input|select)$/i,A=/^([^\.]*)?(?:\.(.+))?$/,B=/\bhover(\.\S+)?\b/,C=/^key/,D=/^(?:mouse|contextmenu)|click/,E=/^(?:focusinfocus|focusoutblur)$/,F=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,G=function(a){var b=F.exec(a);b&&(b[1]=(b[1]||"").toLowerCase(),b[3]=b[3]&&new RegExp("(?:^|\\s)"+b[3]+"(?:\\s|$)"));return b},H=function(a,b){var c=a.attributes||{};return(!b[1]||a.nodeName.toLowerCase()===b[1])&&(!b[2]||(c.id||{}).value===b[2])&&(!b[3]||b[3].test((c["class"]||{}).value))},I=function(a){return f.event.special.hover?a:a.replace(B,"mouseenter$1 mouseleave$1")};
@@ -13,7 +13,7 @@ the scope of this Users Guide. We kindly refer the interested reader to
13
13
  operating systems literature about 'virtual memory' and 'copy-on-write'.
14
14
 
15
15
  The tool `passenger-memory-stats` allows one to easily analyze Phusion Passenger's
16
- and Apache's real memory usage. For example:
16
+ and the web server's real memory usage. For example:
17
17
 
18
18
  -------------------------------------------------------
19
19
  [bash@localhost root]# passenger-memory-stats
@@ -31,6 +31,12 @@ PID PPID Threads VMSize Private Name
31
31
  ### Processes: 8
32
32
  ### Total private dirty RSS: 3.50 MB
33
33
 
34
+ ----------- Nginx processes ------------.
35
+ PID PPID VMSize Resident Name
36
+ ----------------------------------------.
37
+ 51766 51764 82.7 MB 3.9 MB nginx: master process ./objs/nginx
38
+ 51773 51766 82.9 MB 0.9 MB nginx: worker process
39
+
34
40
  --------- Passenger processes ---------.
35
41
  PID Threads VMSize Private Name
36
42
  ---------------------------------------.
@@ -43,8 +49,8 @@ PID Threads VMSize Private Name
43
49
  -------------------------------------------------------
44
50
 
45
51
  The 'Private' or 'private dirty RSS' field shows the *real* memory usage of processes. Here,
46
- we see that all the Apache worker processes only take less than 1 MB memory each.
47
- This is a lot less than the 50 MB-ish memory usage as shown in the 'VMSize' column
52
+ we see that all the Apache and Nginx worker processes only take less than 1 MB memory each.
53
+ This is a lot less than the 50-80 MB-ish memory usage as shown in the 'VMSize' column
48
54
  (which is what a lot of people think is the real memory usage, but is actually not).
49
55
 
50
56
  NOTE: Private dirty RSS reporting only works on Linux. Unfortunately other operating systems
@@ -126,13 +132,13 @@ If one of your application instances is frozen (stopped responding), then you
126
132
  can figure out where it is frozen by killing it with 'SIGABRT'. This will cause the
127
133
  application to raise an exception, with a backtrace.
128
134
 
129
- The exception (with full backtrace information) is normally logged into the Apache
135
+ The exception (with full backtrace information) is normally logged into the web server
130
136
  error log. But if your application or if its web framework has its own exception logging
131
137
  routines, then exceptions might be logged into the application's log files instead.
132
138
  This is the case with Ruby on Rails. So if you kill a Ruby on Rails application with
133
139
  'SIGABRT', please check the application's 'production.log' first (assuming that you're
134
140
  running it in a 'production' environment). If you don't see a backtrace there, check
135
- the Apache error log.
141
+ the web server error log.
136
142
 
137
143
  NOTE: It is safe to kill application instances, even in live environments. Phusion Passenger
138
144
  will restart killed application instances, as if nothing bad happened.
@@ -189,7 +189,11 @@ If the output is not as expected, then please refer to the <<troubleshooting,Tro
189
189
  [float]
190
190
  ==== Step 1: download and extract the tarball
191
191
 
192
- Download the open source Phusion Passenger tarball from link:https://www.phusionpassenger.com/download#open_source[the Phusion Passenger website]. If you want a specific version, please refer to the release archive on link:http://rubyforge.org/frs/?group_id=5873&release_id=46919[RubyForge].
192
+ Download the open source Phusion Passenger tarball from link:https://www.phusionpassenger.com/download#open_source[the Phusion Passenger website]. Specific older versions are not found on the Phusion Passenger website, but are found in the following places:
193
+
194
+ * All versions starting from 4.0.0 can be found on link:https://code.google.com/p/phusion-passenger/downloads/list[Google Code].
195
+ * All versions prior to 4.0.0, except for beta releases and Release Candidates, can be found on link:http://rubyforge.org/frs/?group_id=5873&release_id=46919[RubyForge].
196
+ * All beta releases and Release Candidates prior to 4.0.0 beta 1 can be found on link:https://code.google.com/p/phusion-passenger/downloads/list[Google Code].
193
197
 
194
198
  If you a link:https://www.phusionpassenger.com/enterprise[Phusion Passenger Enterprise] customer, download the Phusion Passenger Enterprise tarball from the link:https://www.phusionpassenger.com/orders[Customer Area]. Also be sure to download the *license key* and save it as '/etc/passenger-enterprise-license'.
195
199
 
@@ -10,15 +10,15 @@ Phusion Passenger solves this problem by implementing 'user switching'. A Rails
10
10
  application is started as the owner of the file 'config/environment.rb',
11
11
  and a Rack application is started as the owner of the file 'config.ru'.
12
12
  So if '/home/webapps/foo/config/environment.rb' is owned by 'joe', then Phusion
13
- Passenger will launch the corresponding Rails application as 'joe' as well.
13
+ Passenger will launch the corresponding application as 'joe' as well.
14
14
 
15
15
  This behavior is the default, and you don't need to configure anything. But
16
16
  there are things that you should keep in mind:
17
17
 
18
18
  - The owner of 'environment.rb'/'config.ru' must have read access to the application's
19
19
  root directory, and read/write access to the application's 'logs' directory.
20
- - This feature is only available if Apache is started by 'root'. This is the
21
- case on most Apache installations.
20
+ - This feature is only available if the web server is started by 'root'. This is the
21
+ case on most installations.
22
22
  - Under no circumstances will applications be run as 'root'. If
23
23
  'environment.rb'/'config.ru' is owned as root or by an unknown user, then the
24
24
  Rails/Rack application will run as the user specified by
@@ -134,11 +134,14 @@ check for this file's timestamp: Phusion Passenger will always restart the
134
134
  application, as long as 'always_restart.txt' exists.
135
135
 
136
136
  NOTE: If you're just developing a Rails application then you probably don't need
137
- this feature. If you set 'RailsEnv development' in your Apache configuration,
137
+ this feature. If you set
138
+ ifdef::apache['RailsEnv development']
139
+ ifdef::nginx['rails_env development']
140
+ in your web server configuration,
138
141
  then Rails will automatically reload your application code after each request.
139
- 'always_restart.txt' is only useful if you're working on Ruby on Rails itself,
140
- or when you're not developing a Rails application and your web framework
141
- does not support code reloading.
142
+ 'always_restart.txt' is mostly useful when you're using a web framework that
143
+ doesn't support code reloading by itself, of when you're working on a web framework
144
+ yourself.
142
145
 
143
146
  [[sub_uri_deployment_uri_fix]]
144
147
  === How to fix broken images/CSS/JavaScript URIs in sub-URI deployments
@@ -9,10 +9,10 @@ For example, suppose that the browser requests '/foo/bar'.
9
9
 
10
10
  1. Phusion Passenger will first check whether this URI maps to a static file, i.e.
11
11
  whether the file 'foo/bar' exists in the web application's 'public' directory.
12
- If it does then Phusion Passenger will serve this file through Apache immediately.
12
+ If it does then Phusion Passenger will serve this file through the web server immediately.
13
13
  2. If that doesn't exist, then Phusion Passenger will check whether the file
14
14
  'foo/bar.html' exists. If it does then Phusion Passenger will serve this file
15
- through Apache immediately.
15
+ through the web server immediately.
16
16
  3. If 'foo/bar.html' doesn't exist either, then Phusion Passenger will forward the
17
17
  request to the underlying web application.
18
18
 
@@ -477,11 +477,6 @@ const command_rec passenger_commands[] = {
477
477
  NULL,
478
478
  OR_OPTIONS | ACCESS_CONF,
479
479
  "The Ruby interpreter to use."),
480
- AP_INIT_TAKE1("PassengerPython",
481
- (Take1Func) cmd_passenger_python,
482
- NULL,
483
- OR_OPTIONS | ACCESS_CONF | RSRC_CONF,
484
- "The Python interpreter to use."),
485
480
  AP_INIT_TAKE1("PassengerLogLevel",
486
481
  (Take1Func) cmd_passenger_log_level,
487
482
  NULL,
@@ -730,7 +725,11 @@ const command_rec passenger_commands[] = {
730
725
  "The environment under which a Rack app must run."),
731
726
 
732
727
  // WSGI-specific settings.
733
- // none
728
+ AP_INIT_TAKE1("PassengerPython",
729
+ (Take1Func) cmd_passenger_python,
730
+ NULL,
731
+ OR_OPTIONS | ACCESS_CONF | RSRC_CONF,
732
+ "The Python interpreter to use."),
734
733
 
735
734
  // Backwards compatibility options.
736
735
  AP_INIT_TAKE1("RailsRuby",
@@ -85,10 +85,6 @@ struct DirConfig {
85
85
  */
86
86
  const char *appRoot;
87
87
 
88
- /** The environment (i.e. value for RACK_ENV) under which
89
- * Rack applications should operate. */
90
- const char *rackEnv;
91
-
92
88
  string appGroupName;
93
89
 
94
90
  /** The spawn method to use. */
@@ -251,7 +251,7 @@ private:
251
251
  }
252
252
 
253
253
  foreach (const ProcessPtr &process, detachedProcesses) {
254
- assert(process->getLifeStatus() == Process::SHUTTING_DOWN);
254
+ assert(process->enabled == Process::DETACHED);
255
255
  assert(process->pqHandle == NULL);
256
256
  }
257
257
  #endif
@@ -323,24 +323,26 @@ private:
323
323
  void removeProcessFromList(const ProcessPtr &process, ProcessList &source) {
324
324
  ProcessPtr p = process; // Keep an extra reference count just in case.
325
325
  source.erase(process->it);
326
- if (process->isAlive()) {
327
- switch (process->enabled) {
328
- case Process::ENABLED:
329
- enabledCount--;
330
- pqueue.erase(process->pqHandle);
331
- process->pqHandle = NULL;
332
- break;
333
- case Process::DISABLING:
334
- disablingCount--;
335
- break;
336
- case Process::DISABLED:
337
- disabledCount--;
338
- break;
339
- default:
340
- P_BUG("Unknown 'enabled' state " << (int) process->enabled);
341
- }
342
- } else {
326
+ switch (process->enabled) {
327
+ case Process::ENABLED:
328
+ assert(&source == &enabledProcesses);
329
+ enabledCount--;
330
+ pqueue.erase(process->pqHandle);
331
+ process->pqHandle = NULL;
332
+ break;
333
+ case Process::DISABLING:
334
+ assert(&source == &disablingProcesses);
335
+ disablingCount--;
336
+ break;
337
+ case Process::DISABLED:
338
+ assert(&source == &disabledProcesses);
339
+ disabledCount--;
340
+ break;
341
+ case Process::DETACHED:
343
342
  assert(&source == &detachedProcesses);
343
+ break;
344
+ default:
345
+ P_BUG("Unknown 'enabled' state " << (int) process->enabled);
344
346
  }
345
347
  }
346
348
 
@@ -366,6 +368,7 @@ private:
366
368
  disabledCount++;
367
369
  } else if (&destination == &detachedProcesses) {
368
370
  assert(process->isAlive());
371
+ process->enabled = Process::DETACHED;
369
372
  } else {
370
373
  P_BUG("Unknown destination list");
371
374
  }
@@ -485,14 +488,6 @@ private:
485
488
  }
486
489
  }
487
490
 
488
- void shutdownAndRemoveProcess(const ProcessPtr &process) {
489
- TRACE_POINT();
490
- const ProcessPtr p = process;
491
- assert(process->canBeShutDown());
492
- removeProcessFromList(process, detachedProcesses);
493
- process->shutdown();
494
- }
495
-
496
491
  bool shutdownCanFinish() const {
497
492
  return getLifeStatus() == SHUTTING_DOWN
498
493
  && enabledCount == 0
@@ -600,10 +595,10 @@ public:
600
595
 
601
596
  /**
602
597
  * When a process is detached, it is stored here until we've confirmed
603
- * that it can be shut down.
598
+ * that the OS process has exited.
604
599
  *
605
600
  * for all process in detachedProcesses:
606
- * process.getLifeStatus() == Process::SHUTTING_DOWN
601
+ * process.enabled == Process::DETACHED
607
602
  * process.pqHandle == NULL
608
603
  */
609
604
  ProcessList detachedProcesses;
@@ -663,7 +658,7 @@ public:
663
658
  void shutdown(const Callback &callback, vector<Callback> &postLockActions) {
664
659
  assert(isAlive());
665
660
 
666
- P_DEBUG("Shutting down group " << name);
661
+ P_DEBUG("Begin shutting down group " << name);
667
662
  shutdownCallback = callback;
668
663
  detachAll(postLockActions);
669
664
  startCheckingDetachedProcesses(true);
@@ -676,11 +671,6 @@ public:
676
671
  lock_guard<boost::mutex> l(lifetimeSyncher);
677
672
  lifeStatus = SHUTTING_DOWN;
678
673
  }
679
- if (shutdownCanFinish()) {
680
- finishShutdown(postLockActions);
681
- } else {
682
- P_DEBUG("Shutdown finalization of group " << name << " has been deferred");
683
- }
684
674
  }
685
675
 
686
676
  SessionPtr get(const Options &newOptions, const GetCallback &callback) {
@@ -863,12 +853,7 @@ public:
863
853
  }
864
854
 
865
855
  addProcessToList(process, detachedProcesses);
866
- process->setShuttingDown();
867
- if (process->canBeShutDown()) {
868
- shutdownAndRemoveProcess(process);
869
- } else {
870
- startCheckingDetachedProcesses(false);
871
- }
856
+ startCheckingDetachedProcesses(false);
872
857
  }
873
858
 
874
859
  /**
@@ -882,15 +867,12 @@ public:
882
867
  foreach (ProcessPtr process, enabledProcesses) {
883
868
  addProcessToList(process, detachedProcesses);
884
869
  process->pqHandle = NULL;
885
- process->setShuttingDown();
886
870
  }
887
871
  foreach (ProcessPtr process, disablingProcesses) {
888
872
  addProcessToList(process, detachedProcesses);
889
- process->setShuttingDown();
890
873
  }
891
874
  foreach (ProcessPtr process, disabledProcesses) {
892
875
  addProcessToList(process, detachedProcesses);
893
- process->setShuttingDown();
894
876
  }
895
877
 
896
878
  enabledProcesses.clear();
@@ -370,7 +370,7 @@ Group::onSessionInitiateFailure(const ProcessPtr &process, Session *session) {
370
370
  // Standard resource management boilerplate stuff...
371
371
  PoolPtr pool = getPool();
372
372
  unique_lock<boost::mutex> lock(pool->syncher);
373
- assert(!process->isShutDown());
373
+ assert(process->isAlive());
374
374
  assert(isAlive() || getLifeStatus() == SHUTTING_DOWN);
375
375
 
376
376
  UPDATE_TRACE_POINT();
@@ -390,7 +390,7 @@ Group::onSessionClose(const ProcessPtr &process, Session *session) {
390
390
  // Standard resource management boilerplate stuff...
391
391
  PoolPtr pool = getPool();
392
392
  unique_lock<boost::mutex> lock(pool->syncher);
393
- assert(!process->isShutDown());
393
+ assert(process->isAlive());
394
394
  assert(isAlive() || getLifeStatus() == SHUTTING_DOWN);
395
395
 
396
396
  P_TRACE(2, "Session closed for process " << process->inspect());
@@ -399,9 +399,11 @@ Group::onSessionClose(const ProcessPtr &process, Session *session) {
399
399
 
400
400
  /* Update statistics. */
401
401
  process->sessionClosed(session);
402
- Process::LifeStatus lifeStatus = process->getLifeStatus();
403
- assert(process->enabled == Process::ENABLED || process->enabled == Process::DISABLING);
404
- if (process->enabled == Process::ENABLED && lifeStatus == Process::ALIVE) {
402
+ assert(process->getLifeStatus() == Process::ALIVE);
403
+ assert(process->enabled == Process::ENABLED
404
+ || process->enabled == Process::DISABLING
405
+ || process->enabled == Process::DETACHED);
406
+ if (process->enabled == Process::ENABLED) {
405
407
  pqueue.decrease(process->pqHandle, process->utilization());
406
408
  }
407
409
 
@@ -410,16 +412,6 @@ Group::onSessionClose(const ProcessPtr &process, Session *session) {
410
412
  */
411
413
  assert(!process->atFullUtilization());
412
414
 
413
- if (lifeStatus == Process::SHUTTING_DOWN) {
414
- UPDATE_TRACE_POINT();
415
- if (process->canBeShutDown()) {
416
- shutdownAndRemoveProcess(process);
417
- }
418
- verifyInvariants();
419
- verifyExpensiveInvariants();
420
- return;
421
- }
422
-
423
415
  bool detachingBecauseOfMaxRequests = false;
424
416
  bool detachingBecauseCapacityNeeded = false;
425
417
  bool shouldDetach =
@@ -521,7 +513,10 @@ Group::lockAndAsyncOOBWRequestIfNeeded(const ProcessPtr &process, DisableResult
521
513
 
522
514
  void
523
515
  Group::asyncOOBWRequestIfNeeded(const ProcessPtr &process) {
524
- if (process->oobwStatus != Process::OOBW_REQUESTED || !process->isAlive()) {
516
+ if (process->oobwStatus != Process::OOBW_REQUESTED
517
+ || process->enabled == Process::DETACHED
518
+ || !process->isAlive())
519
+ {
525
520
  return;
526
521
  }
527
522
  if (process->enabled == Process::ENABLED) {
@@ -715,7 +710,7 @@ Group::spawnThreadRealMain(const SpawnerPtr &spawner, const Options &options, un
715
710
  }
716
711
 
717
712
  UPDATE_TRACE_POINT();
718
- ScopeGuard guard(boost::bind(Process::maybeShutdown, process));
713
+ ScopeGuard guard(boost::bind(Process::forceTriggerShutdownAndCleanup, process));
719
714
  unique_lock<boost::mutex> lock(pool->syncher);
720
715
 
721
716
  if (!isAlive()) {
@@ -897,9 +892,14 @@ Group::finalizeRestart(GroupPtr self, Options options, SpawnerFactoryPtr spawner
897
892
  }
898
893
  }
899
894
 
895
+ /**
896
+ * The `immediately` parameter only has effect if the detached processes checker
897
+ * thread is active. It means that, if the thread is currently sleeping, it should
898
+ * wake up immediately and perform work.
899
+ */
900
900
  void
901
901
  Group::startCheckingDetachedProcesses(bool immediately) {
902
- if (!detachedProcessesCheckerActive && !detachedProcesses.empty()) {
902
+ if (!detachedProcessesCheckerActive) {
903
903
  P_DEBUG("Starting detached processes checker");
904
904
  getPool()->nonInterruptableThreads.create_thread(
905
905
  boost::bind(&Group::detachedProcessesCheckerMain, this, shared_from_this()),
@@ -916,12 +916,13 @@ void
916
916
  Group::detachedProcessesCheckerMain(GroupPtr self) {
917
917
  TRACE_POINT();
918
918
  PoolPtr pool = getPool();
919
+ unique_lock<boost::mutex> lock(pool->syncher);
919
920
 
920
- while (!this_thread::interruption_requested()) {
921
- unique_lock<boost::mutex> lock(pool->syncher);
921
+ while (true) {
922
922
  assert(detachedProcessesCheckerActive);
923
923
 
924
- if (getLifeStatus() == SHUT_DOWN) {
924
+ if (getLifeStatus() == SHUT_DOWN || this_thread::interruption_requested()) {
925
+ UPDATE_TRACE_POINT();
925
926
  P_DEBUG("Stopping detached processes checker");
926
927
  detachedProcessesCheckerActive = false;
927
928
  break;
@@ -929,19 +930,35 @@ Group::detachedProcessesCheckerMain(GroupPtr self) {
929
930
 
930
931
  UPDATE_TRACE_POINT();
931
932
  if (!detachedProcesses.empty()) {
932
- P_TRACE(2, "Checking whether any detached processes have exited...");
933
+ P_TRACE(2, "Checking whether any of the " << detachedProcesses.size() <<
934
+ " detached processes have exited...");
933
935
  ProcessList::iterator it = detachedProcesses.begin();
934
936
  ProcessList::iterator end = detachedProcesses.end();
935
937
  while (it != end) {
936
938
  const ProcessPtr process = *it;
937
- if (process->canBeShutDown()) {
938
- it++;
939
- P_DEBUG("Detached process " << process->inspect() << " has exited.");
940
- shutdownAndRemoveProcess(process);
941
- } else {
942
- P_DEBUG("Detached process " << process->inspect() << " not yet exited. "
943
- "sessions = " << process->sessions);
939
+ switch (process->getLifeStatus()) {
940
+ case Process::ALIVE:
941
+ if (process->canTriggerShutdown()) {
942
+ P_DEBUG("Detached process " << process->inspect() <<
943
+ " has 0 active sessions now. Triggering shutdown.");
944
+ process->triggerShutdown();
945
+ assert(process->getLifeStatus() == Process::SHUTDOWN_TRIGGERED);
946
+ }
944
947
  it++;
948
+ break;
949
+ case Process::SHUTDOWN_TRIGGERED:
950
+ if (process->canCleanup()) {
951
+ P_DEBUG("Detached process " << process->inspect() << " has shut down. Cleaning up associated resources.");
952
+ process->cleanup();
953
+ assert(process->getLifeStatus() == Process::DEAD);
954
+ it++;
955
+ removeProcessFromList(process, detachedProcesses);
956
+ } else {
957
+ it++;
958
+ }
959
+ break;
960
+ default:
961
+ P_BUG("Unknown 'lifeStatus' state " << (int) process->getLifeStatus());
945
962
  }
946
963
  }
947
964
  }
@@ -970,6 +987,8 @@ Group::detachedProcessesCheckerMain(GroupPtr self) {
970
987
  verifyExpensiveInvariants();
971
988
  }
972
989
 
990
+ // Not all processes can be shut down yet. Sleep for a while unless
991
+ // someone wakes us up.
973
992
  UPDATE_TRACE_POINT();
974
993
  detachedProcessesCheckerCond.timed_wait(lock,
975
994
  posix_time::milliseconds(10));
@@ -1013,13 +1032,13 @@ Group::generateSecret(const SuperGroupPtr &superGroup) {
1013
1032
 
1014
1033
  SuperGroupPtr
1015
1034
  Process::getSuperGroup() const {
1016
- assert(getLifeStatus() != SHUT_DOWN);
1035
+ assert(getLifeStatus() != DEAD);
1017
1036
  return getGroup()->getSuperGroup();
1018
1037
  }
1019
1038
 
1020
1039
  string
1021
1040
  Process::inspect() const {
1022
- assert(getLifeStatus() != SHUT_DOWN);
1041
+ assert(getLifeStatus() != DEAD);
1023
1042
  stringstream result;
1024
1043
  result << "(pid=" << pid;
1025
1044
  GroupPtr group = getGroup();
@@ -1055,7 +1074,7 @@ Session::getGroup() const {
1055
1074
  void
1056
1075
  Session::requestOOBW() {
1057
1076
  ProcessPtr process = getProcess();
1058
- assert(!process->isShutDown());
1077
+ assert(process->isAlive());
1059
1078
  process->getGroup()->requestOOBW(process);
1060
1079
  }
1061
1080