Re: HTTP/2 in massive file transfers
That's a great benchmark, José. A couple of questions: 1. When using http 1.1, is your connection over SSL? I assume that your h2 connection is over ssl, and that might account for a speed penalty. 2. Have you tried this on other h2 implementations (h2o, nginx)? 3. Can you take some other data points? If you just have 100 shards rather than 1000, how does that affect the results? 4. Can you also vary the size of each shard? Publishing your results in a more comprehensive study would be quite valuable. -Josh On Tue, Mar 8, 2016 at 6:33 AM, Molinawrote: > Hello, > > I’m testing the HTTP/2 performance to add support to the software I’m > working for. My benchmark consist on an apache 2.4.17 server with the > following http2-related configuration: > > LoadModule http2_module modules/mod_http2.so > > Protocols h2c http/1.1 > H2WindowSize 146000 > H2StreamMaxMemSize 146000 > H2MinWorkers 8 > H2Direct on > LogLevel http2:info > H2MaxSessionStreams 100 > H2SessionExtraFiles 1000 > H2MaxWorkers 100 > > > The rest is simply the default apache configuration. > My client is a C application that downloads 1024 files of exactly 1MiB > each, so totally 1GB. When performing the test with normal HTTP/1.1 the > download speed is around 20MiB/s, while when using HTTP/2 is 1.5MiB/s. The > client uses exactly one multiplexed connection and works as expected > Lastly, the client and server are located in center Europe and center USA > respectively to increase the impact of opening many HTTP/1.1 connections > with such a high physical distance due to latency. > > I tried to increase the Linux window size, as well as the TCP buffer to > increase the download speed, but without success so far. > > Is there some configuration parameter I’m missing to make it perform > better? Or perhaps the module itself needs an special configuration for > such a use case? > > Thanks a lot in advance. Best regards, > José Molina > >
Re: Sharing information across Apache child processes
There's a variation on this theme you might consider. You can use a few counters in shared memory, and save config information in a file. If one of the child processes learns of a config update (say by handling an HTTP request for one from somewhere) it can update the file (atomically, say, via write-to-temp-and-rename) and bump a shared-memory counter (atomically via shared-memory mutex). Other child processes can quickly poll on counter-changes and re-read config files when they change. The advantage of this approach over storing the whole config in shared-memory is that we only put a fixed number of integers in shared memory, rather than our whole configuration structure, which might be large or vary in size depending on the config. mod_pagespeed uses this technique https://code.google.com/p/modpagespeed/source/browse/trunk/src/pagespeed/kernel/cache/purge_context.h. Note there is no apr code directly in that file as it's abstracted behind some C++ interfaces, but 'Variable' is really an int64's worth of mutexed shared memory in operation. -Josh - On Tue, Sep 30, 2014 at 9:20 AM, Abdi Abdirahman abd.moha...@gmail.com wrote: On 09/29/2014 05:14 PM, Sorin Manolache wrote: On 2014-09-29 13:39, Rajalakshmi Iyer wrote: Hello, I have a requirement whereby my application's configuration information (comprising a few complex data structures) needs to be shared across the various Apache child processes. Currently, the configuration is being individually loaded by each child process, which makes it hard for configuration changes to propagate. What is the best way / place to have a common configuration for the application? Please advise. I suppose you want to update the configuration without running apache2 -k graceful (or apache2ctl graceful). In this case you could use a segment of memory that is shared across the apache children. You'll have to create the shared segment memory before the parent forks its children (for example in post_config). The shared memory is then inherited by the forked children. You'll need a method to update the contents of the shared memory segment and a multiple-readers-single-writer inter-process exclusion mechanism in order to safely read and write from the shared segment. Sorin Hello All, You can check out mod_cluster approach (https://github.com/ modcluster/mod_cluster/tree/master/native/mod_proxy_cluster) - it uses shared memory as data storage and additional thread per process to check updates in storage. This way you'll keep per-process module config in sync with shared data. Not perfect solution though, but I doubt that there is any flawless way to share config structures. Best regards, Abdi A.
Re: sequence of request
Yes, in particular, the gdb feature that can help determine who is changing r-filename is hardware watchpoints: http://sourceware.org/gdb/onlinedocs/gdb/Set-Watchpoints.html 1. Set a breakpoint at a line of code where you believe r-filename is correct 2. Start up Apache with run -X 3. Issue a request to the server to hit the line of code where r-filename is set. 4. Set up a hardware watchpoint with (gdb) p r-filename $1 = (char**) 0x (gdb) watch *$1 Hardware Watchpoint 2 Depending on what you've done in the debugger beforehand, the $1 may be something like $3 or $4. In that case use watch *$3, etc. -Josh On Thu, Jul 24, 2014 at 6:54 AM, Eric Covener cove...@gmail.com wrote: On Thu, Jul 24, 2014 at 12:51 AM, Donatas Abraitis donatas.abrai...@gmail.com wrote: Hello guys, is it possible to know the sequence of request is handled? I mean which module takes precedence? Because I need to debug why r-filename becomes not so as I expected. mod_info shows you the order the loaded modules will run in for various phases. A debugger can also tell you when it changes. -- Eric Covener cove...@gmail.com
associating an object with a request
Hi, I want to create a data structure and associate it with a request_rec*, which will be accessed by multiple filters and handlers in our module. I know I can use the filter-ctx for general data structure storage, but I actually want something that will be accessed by multiple filters and handlers without having to rebuild it. Currently our module (mod_pagespeed) rebuilds the same context multiple times and this can be a little more compute-intensive than desired. Of course I can make my own std::maprequest_rec*, MyAwesomeStructure* and put the map in my own module config, cleaning up and freeing my structure when the request_rec's pool is deleted via a hook. But I wanted to see if there was a more direct place to stash pointers. I also know I can put strings in request-notes but I need to put a data structure, not a string. Is there an easy way to do this? Or should I use a map? -Josh
Re: associating an object with a request
Thanks Eric. That looks perfect! I'll give it a try. On Wed, Apr 23, 2014 at 4:34 PM, Eric Covener cove...@gmail.com wrote: On Wed, Apr 23, 2014 at 4:31 PM, Joshua Marantz jmara...@google.com wrote: I want to create a data structure and associate it with a request_rec*, which will be accessed by multiple filters and handlers in our module. You can allocate your structure from r-pool and associate it with the current request with ap_get|set_module_config(r-request_config, your-module) -- Eric Covener cove...@gmail.com
Re: problem with different version of openssl in Apache and apache module
We faced this exact issue (openssl clashes with other linked-in versions) in mod_pagespeed and ngx_pagespeed, its nginx equivalent. We solved this problem in our Apache module because we linked mod_pagespeed.so hiding all the symbols other than the module entry-point into Apache. Here's the link command: g++ -shared -pthread -Wl,-z,noexecstack -fPIC \ -Wl,--version-script=build/mod_pagespeed.map \ -Wl,-soname=libmod_pagespeed.so \ -o out/Debug/obj.target/net/instaweb/libmod_pagespeed.so \ -Wl,--start-group \ object file list . \ -Wl,--end-group -lrt Where mod_pagespeed.map contains: { /* Make sure we don't export anything unneeded */ global: pagespeed_module; local: *; }; In nginx we didn't have such a clean solution, since nginx just uses a flat link of .o files. Our resolution is in this script: https://code.google.com/p/modpagespeed/source/browse/trunk/src/net/instaweb/automatic/rename_c_symbols.sh. This script is specific to our purpose but it might contain enough ideas that you could hack it to meet yours. This script is applied to a .a file that includes the definition and use of a version of openssl. It simply renames all the C symbols in the .a, leaving the C++ ones intact, and this works for us because the .a in question has a C++ interface. You could hack the script to just rename the openssl symbols and your use of them, and you can extract the list of openssl symbols by grepping the output of nm libopenssl.a, following some of the patterns in our rename_c_symbols.sh script. -Josh On Fri, Dec 20, 2013 at 5:57 AM, Rainer Jung rainer.j...@kippdata.dewrote: On 20.12.2013 10:51, Alex Bligh wrote: On 19 Dec 2013, at 19:29, Hong wrote: I wrote an Apache module that call functions in openssl library to sign the messages. The module is dynamic linked to openssl library 1.0.1d when I built it. It works fine when it is loaded into the Apache that was also built with the same version of openssl. But if Apache was built with openssl 0.9.8x, segfault occurred. Is there anything I can do for my built so it also works in the Apache which was built with older version of openssl? Static link to openssl? That often doesn't help, because the runtime linker by default searches symbols in load order. So if mod_ssl was linked against OpenSSL 0.9.8 and mod_xyz was linked against 1.0.1 and mod_ssl gets loaded before mod_xyz, then OpenSSL 0.9.8 gets also loaded before (either as a shared lib or as statically linked into mod_ssl). Now when later the runtime linker needs to resolve an OpenSSL symbol (e.g. function name) because it is used in mod_xyz it will first look in OpenSSL 0.9.8 for the symbol and only if not found there in 1.0.1. AFAIK there's no really good solution. Some platforms support symbolic linking (ld -Bsymbolic), which changes the search order for the runtime linker. With symbolic linking the runtime linker first looks into the dependencies of the component needing a symbol before searching through everything in load order. That means symbols needed by mod_xyz would indeed be searched in OpenSSL 1.0.1 first and in OpenSSL 0.9.8 only as a fallback. Note that this isn't the same as a symbolic file system link. There's a couple of negative side effects though. Another solution should be possible using a linker script but to implement that you would need to do quite a bit of work integrating the linker script into the OpenSSL build. All of this is somehow fragile. It should be more robust to support different combinations with different builds. As pointers have a look at: https://sourceware.org/binutils/docs-2.24/ld/Options.html#Options (short description of ld -Bsymbolic) http://www.akkadia.org/drepper/dsohowto.pdf (search for symbolic, detailed explanations) http://www.macieira.org/blog/2012/01/sorry-state-of-dynamic-libraries-on-linux/ http://software.intel.com/en-us/articles/performance-tools-for-software-developers-bsymbolic-can-cause-dangerous-side-effects http://docs.oracle.com/cd/E19683-01/817-3677/817-3677.pdf Mostly about Solaris but nevertheless full of interesting stuff. Regards, Rainer
Re: Apache Buckets and Brigade
I have a crazy idea for you. Maybe this is overkill but this sounds like it'd be natural to add to mod_pagespeed http://modpagespeed.com as a new filter. Here's some code you might use as a template https://code.google.com/p/modpagespeed/source/browse/trunk/src/net/instaweb/rewriter/collapse_whitespace_filter.cc one thing we've thought of doing is providing a generic text-substitution filter that would take strings in character-blocks and do arbitrary substitutions in them, that could be specified in the .conf file: ModPagespeedSubstitute oldString newString You are right that text-blocks in Apache output filters can be split arbitrarily across buckets, but mod_pagespeed takes care of that in an HTML-centric way, breaking up blocks on html tokens. A block of free-format text would be treated as a single atomic token independent of the structure of the incoming bucket brigade. Let me know if you'd like to discuss this further. -Josh On Wed, May 1, 2013 at 8:54 AM, Sindhi Sindhi sindhi@gmail.com wrote: Hello, Thanks a lot for providing answers to my earlier emails with subject Apache C++ equivalent of javax.servlet.Filter. I really appreciate your help. I had another question. My requirement is something like this - I have a huge html file that I have copied into the Apache htdocs folder. In my C++ Apache module, I want to get this html file contents and remove/replace some strings. Say I have a HTML file that has the string oldString appearing 3 times in the file. My requirement is to replace oldString with the new string newString. I have already written a C++ function that has a signature like this - char* processHTML(char* inHTMLString) { // char* newHTMLWithNewString = code to replace all occurrences of oldString with newString return newHTMLWithNewString; } The above function does a lot more than just string replace, it has lot of business logic implemented and finally returns the new HTML string. I want to call processHTML() inside my C++ Apache module. As I know Apache maintains an internal data structure called Buckets and Brigades which actually contain the HTML file data. My question is, is the entire HTML file content (in my case the html file is huge) residing in a single bucket? Means, when I fetch one bucket at a time from a brigade, can I be sure that the entire HTML file data from html to /html can be found in a single bucket? For ex. if my html file looks like this - html .. .. oldString ... oldString...oldString.. .. /html When I iterate through all buckets of a brigade, will I find my entire HTML file content in a single bucket OR the HTML file content can be present in multiple buckets, say like this - case1: bucket-1 contents = html .. .. oldString ... oldString...oldString.. .. /html case2: bucket-1 contents = html .. .. oldStr bucket-2 contents = ing ... oldString...oldString.. .. /html If its case2, then the the function processHTML() I have written will not work because it searches for the entire string oldString and in case2 oldString is found only partially. Thanks a lot.
Re: Apache Buckets and Brigade
On Wed, May 1, 2013 at 12:14 PM, Sindhi Sindhi sindhi@gmail.com wrote: Thanks to all for the reply. Josh, the concern I mentioned was, we may not want mod_pagespeed to modify the in-memory HTML content. The only change we may want to see in our HTML will be that the old strings are replaced by the new strings after applying our business logic which is already done by the C++ filter module I have written. This C++ filter implements all our business logic and takes an input buffer that is expected to be the entire HTML file content. So the Yeah the filter I gave you gives you only a block of HTML characters. E.g. if you have diva b c d ie/i f/div then you'll get this as 3 calls to Characters: a b c d , e, and f. Other than that, the Characters method I pointed you to has exactly the interface you asked for: it gets you an entire block of HTML text in one modifiable std::string which you can mutate at will. And it irons out all the brigade stuff for you. You can configure mod_pagespeed to run just one filter so no other modifications are made. But it looks like you probably need to read Nick's book. You can also read mod_deflate.c or one of the other content-modifying filters such as mod_sed or mod_substitute. -Josh
Re: apr_memcache operation timeouts
Thanks very much for doing this, Jeff. Unfortunately scanning your diff I think you wound up taking a snapshot of a patch I'd uploaded to the bug, but not updated after several subsequent bug fixes. The golden copies are in https://code.google.com/p/modpagespeed/source/browse/#svn%2Ftrunk%2Fsrc%2Fthird_party%2Faprutil: https://code.google.com/p/modpagespeed/source/browse/trunk/src/third_party/aprutil/apr_memcache2.c https://code.google.com/p/modpagespeed/source/browse/trunk/src/third_party/aprutil/apr_memcache2.h After we released our module we had a few small tweaks and bug-fixes based on external feedback for our module. Those versions have now been stable for 3.5 months, with multiple users reporting success with our memcached integration, so I'm hopeful that they have settled into a stable state. What's the best way to go from here? -Josh On Thu, Mar 14, 2013 at 10:45 AM, Jeff Trawick traw...@gmail.com wrote: On Tue, Mar 12, 2013 at 1:56 PM, Jeff Trawick traw...@gmail.com wrote: On Mon, Mar 11, 2013 at 3:50 PM, Joshua Marantz jmara...@google.com wrote: ping! Please don't hesitate to push back and tell me if I can supply the patch or update in some easier-to-digest form. In particular, while I have rigorously stress-tested this change using mod_pagespeed's unit test, system-test, and load-test framework, I don't really understand what the testing flow is for APR. I'd be happy to add unit-tests for that if someone points me to a change-list or patch-file that does it properly. -Josh I'll try hard to work on this in the next couple of days. It would be great to have fixes in APR-Util 1.5.x, which we hope to work on later this week. Attached is a first pass at getting your patch to apr trunk. Can you confirm that I didn't break your tests? (It passes the apr tests, but that may not mean much.) On Thu, Nov 1, 2012 at 8:04 AM, Joshua Marantz jmara...@google.com wrote: I have completed a solution to this problem, which can be a drop-in update for the existing apr_memcache.c. It is now checked in for my module as http://code.google.com/p/modpagespeed/source/browse/trunk/src/third_party/aprutil/apr_memcache2.c . It differs from the solution in https://issues.apache.org/bugzilla/show_bug.cgi?id=51065 in that: - It doesn't require an API change; it but it enforces the 50ms timeout that already exists for apr_multgetp for all operations. - It works under my load test (which I found is not true of the patch in 51065). For my own purposes, I will be shipping my module with apr_memcache2 so I get the behavior I want regardless of what version of Apache is installed. But I'd like to propose my patch for apr_memcache.c. The patch is attached, and I've also submitted it as an alternative patch to bug 51065. If you agree with the strategy I used to solve this problem, then please let me know if I can help with any changes required to get this into the main distribution, On Mon, Oct 22, 2012 at 5:21 PM, Joshua Marantz jmara...@google.comwrote: I've had some preliminary success with my own variant of apr_memcache.c (creatively called apr_memcache2.c). Rather than setting the socket timeout, I've been mimicing the timeout strategy I saw in apr_memcache_multgetp, by adding a new helper method: static apr_status_t wait_for_server_or_timeout(apr_pool_t* temp_pool, apr_memcache2_conn_t* conn) { apr_pollset_t* pollset; apr_status_t rv = apr_pollset_create(pollset, 1, temp_pool, 0); if (rv == APR_SUCCESS) { apr_pollfd_t pollfd; pollfd.desc_type = APR_POLL_SOCKET; pollfd.reqevents = APR_POLLIN; pollfd.p = temp_pool; pollfd.desc.s = conn-sock; pollfd.client_data = NULL; apr_pollset_add(pollset, pollfd); apr_int32_t queries_recvd; const apr_pollfd_t* activefds; rv = apr_pollset_poll(pollset, MULT_GET_TIMEOUT, queries_recvd, activefds); if (rv == APR_SUCCESS) { assert(queries_recvd == 1); assert(activefds-desc.s == conn-sock); assert(activefds-client_data == NULL); } } return rv; } And calling that before many of the existing calls to get_server_line as: rv = wait_for_server_or_timeout_no_pool(conn); if (rv != APR_SUCCESS) { ms_release_conn(ms, conn); return rv; } This is just an experiment; I think I can streamline this by pre-populating the pollfd structure as part of the apr_memcache_conn_t (actually now apr_memcache2_conn_t). I have two questions about this: 1. I noticed the version of apr_memcache.c that ships with Apache 2.4 is somewhat
Re: apr_memcache operation timeouts
ping! Please don't hesitate to push back and tell me if I can supply the patch or update in some easier-to-digest form. In particular, while I have rigorously stress-tested this change using mod_pagespeed's unit test, system-test, and load-test framework, I don't really understand what the testing flow is for APR. I'd be happy to add unit-tests for that if someone points me to a change-list or patch-file that does it properly. -Josh On Thu, Nov 1, 2012 at 8:04 AM, Joshua Marantz jmara...@google.com wrote: I have completed a solution to this problem, which can be a drop-in update for the existing apr_memcache.c. It is now checked in for my module as http://code.google.com/p/modpagespeed/source/browse/trunk/src/third_party/aprutil/apr_memcache2.c . It differs from the solution in https://issues.apache.org/bugzilla/show_bug.cgi?id=51065 in that: - It doesn't require an API change; it but it enforces the 50ms timeout that already exists for apr_multgetp for all operations. - It works under my load test (which I found is not true of the patch in 51065). For my own purposes, I will be shipping my module with apr_memcache2 so I get the behavior I want regardless of what version of Apache is installed. But I'd like to propose my patch for apr_memcache.c. The patch is attached, and I've also submitted it as an alternative patch to bug 51065. If you agree with the strategy I used to solve this problem, then please let me know if I can help with any changes required to get this into the main distribution, On Mon, Oct 22, 2012 at 5:21 PM, Joshua Marantz jmara...@google.comwrote: I've had some preliminary success with my own variant of apr_memcache.c (creatively called apr_memcache2.c). Rather than setting the socket timeout, I've been mimicing the timeout strategy I saw in apr_memcache_multgetp, by adding a new helper method: static apr_status_t wait_for_server_or_timeout(apr_pool_t* temp_pool, apr_memcache2_conn_t* conn) { apr_pollset_t* pollset; apr_status_t rv = apr_pollset_create(pollset, 1, temp_pool, 0); if (rv == APR_SUCCESS) { apr_pollfd_t pollfd; pollfd.desc_type = APR_POLL_SOCKET; pollfd.reqevents = APR_POLLIN; pollfd.p = temp_pool; pollfd.desc.s = conn-sock; pollfd.client_data = NULL; apr_pollset_add(pollset, pollfd); apr_int32_t queries_recvd; const apr_pollfd_t* activefds; rv = apr_pollset_poll(pollset, MULT_GET_TIMEOUT, queries_recvd, activefds); if (rv == APR_SUCCESS) { assert(queries_recvd == 1); assert(activefds-desc.s == conn-sock); assert(activefds-client_data == NULL); } } return rv; } And calling that before many of the existing calls to get_server_line as: rv = wait_for_server_or_timeout_no_pool(conn); if (rv != APR_SUCCESS) { ms_release_conn(ms, conn); return rv; } This is just an experiment; I think I can streamline this by pre-populating the pollfd structure as part of the apr_memcache_conn_t (actually now apr_memcache2_conn_t). I have two questions about this: 1. I noticed the version of apr_memcache.c that ships with Apache 2.4 is somewhat different from the one that ships with Apache 2.2. In particular the 2.4 version cannot be compiled against the headers that come with a 2.2 distribution. Is there any downside to taking my hacked 2.2 apr_memcache.c and running it in Apache 2.4? Or should I maintain two hacks? 2. This seems wasteful in terms of system calls. I am making an extra call to poll, rather than relying on the socket timeout. The socket timeout didn't work as well as this though. Does anyone have any theories as to why, or what could be done to the patch in https://issues.apache.org/bugzilla/show_bug.cgi?id=51065 to work? -Josh On Fri, Oct 19, 2012 at 9:25 AM, Joshua Marantz jmara...@google.comwrote: Following up: I tried doing what I suggested above: patching that change into my own copy of apr_memcache.c It was first of all a bad idea to pull in only part of apr_memcache.c because that file changed slightly between 2.2 and 2.4 and our module works in both. I was successful making my own version of apr_memcache (renaming entry-points apr_memcache2*) that I could hack. But if I changed the socket timeout from -1 to 10 seconds, then the system behaved very poorly under load test (though it worked fine in our unit-tests and system-tests). In other words, I think the proposed patch that Jeff pointed to above is not really working (as he predicted). This test was done without SIGSTOPing the memcached; it would timeout under our load anyway and thereafter behave poorly. I'm going to follow up on that bugzilla entry, but for now I'm going to pursue my own complicated mechanism of timing out the calls
Re: apr_memcache operation timeouts
I have completed a solution to this problem, which can be a drop-in update for the existing apr_memcache.c. It is now checked in for my module as http://code.google.com/p/modpagespeed/source/browse/trunk/src/third_party/aprutil/apr_memcache2.c . It differs from the solution in https://issues.apache.org/bugzilla/show_bug.cgi?id=51065 in that: - It doesn't require an API change; it but it enforces the 50ms timeout that already exists for apr_multgetp for all operations. - It works under my load test (which I found is not true of the patch in 51065). For my own purposes, I will be shipping my module with apr_memcache2 so I get the behavior I want regardless of what version of Apache is installed. But I'd like to propose my patch for apr_memcache.c. The patch is attached, and I've also submitted it as an alternative patch to bug 51065. If you agree with the strategy I used to solve this problem, then please let me know if I can help with any changes required to get this into the main distribution, On Mon, Oct 22, 2012 at 5:21 PM, Joshua Marantz jmara...@google.com wrote: I've had some preliminary success with my own variant of apr_memcache.c (creatively called apr_memcache2.c). Rather than setting the socket timeout, I've been mimicing the timeout strategy I saw in apr_memcache_multgetp, by adding a new helper method: static apr_status_t wait_for_server_or_timeout(apr_pool_t* temp_pool, apr_memcache2_conn_t* conn) { apr_pollset_t* pollset; apr_status_t rv = apr_pollset_create(pollset, 1, temp_pool, 0); if (rv == APR_SUCCESS) { apr_pollfd_t pollfd; pollfd.desc_type = APR_POLL_SOCKET; pollfd.reqevents = APR_POLLIN; pollfd.p = temp_pool; pollfd.desc.s = conn-sock; pollfd.client_data = NULL; apr_pollset_add(pollset, pollfd); apr_int32_t queries_recvd; const apr_pollfd_t* activefds; rv = apr_pollset_poll(pollset, MULT_GET_TIMEOUT, queries_recvd, activefds); if (rv == APR_SUCCESS) { assert(queries_recvd == 1); assert(activefds-desc.s == conn-sock); assert(activefds-client_data == NULL); } } return rv; } And calling that before many of the existing calls to get_server_line as: rv = wait_for_server_or_timeout_no_pool(conn); if (rv != APR_SUCCESS) { ms_release_conn(ms, conn); return rv; } This is just an experiment; I think I can streamline this by pre-populating the pollfd structure as part of the apr_memcache_conn_t (actually now apr_memcache2_conn_t). I have two questions about this: 1. I noticed the version of apr_memcache.c that ships with Apache 2.4 is somewhat different from the one that ships with Apache 2.2. In particular the 2.4 version cannot be compiled against the headers that come with a 2.2 distribution. Is there any downside to taking my hacked 2.2 apr_memcache.c and running it in Apache 2.4? Or should I maintain two hacks? 2. This seems wasteful in terms of system calls. I am making an extra call to poll, rather than relying on the socket timeout. The socket timeout didn't work as well as this though. Does anyone have any theories as to why, or what could be done to the patch in https://issues.apache.org/bugzilla/show_bug.cgi?id=51065 to work? -Josh On Fri, Oct 19, 2012 at 9:25 AM, Joshua Marantz jmara...@google.comwrote: Following up: I tried doing what I suggested above: patching that change into my own copy of apr_memcache.c It was first of all a bad idea to pull in only part of apr_memcache.c because that file changed slightly between 2.2 and 2.4 and our module works in both. I was successful making my own version of apr_memcache (renaming entry-points apr_memcache2*) that I could hack. But if I changed the socket timeout from -1 to 10 seconds, then the system behaved very poorly under load test (though it worked fine in our unit-tests and system-tests). In other words, I think the proposed patch that Jeff pointed to above is not really working (as he predicted). This test was done without SIGSTOPing the memcached; it would timeout under our load anyway and thereafter behave poorly. I'm going to follow up on that bugzilla entry, but for now I'm going to pursue my own complicated mechanism of timing out the calls from my side. -Josh On Thu, Oct 18, 2012 at 10:46 AM, Joshua Marantz jmara...@google.comwrote: Thanks Jeff, that is very helpful. We are considering a course of action and before doing any work toward this, I'd like to understand the pitfalls from people that understand Apache better than us. Here's our reality: we believe we need to incorporate memcached for mod_pagespeed http://modpagespeed.com to scale effectively for very large sites hosting providers. We are fairly close (we think) to releasing
Forcing Apache to exit on startup
Hi, Our module has multiple confirmation parameters. There is a case where if you have option A and option B, then you must also specify option C, otherwise Bad things can happen that are a lot easier to debug on startup than they are after the server is running. I know how to force 'apachectl' to exit with a nice error message if I don't like the value of option A or option B. I can do that in the function-pointer I provide in my option-table by returning a non-null char* message. But in this case I want to exit nicely from the function I have registered with ap_hook_child_init, having noticed that option A and B are set but not C. Is that possible? By nicely, I mean that the user types: % sudo /etc/init.d/apachectl restart Error in pagespeed.conf: if you have option A and B specified, you must specify a value for option C. At that point either the server would not be running, or it would still be in whatever state it was previously in. Is this possible? Currently our solution is to log an error and call abort(), and it's not very nice! -Josh
Re: apr_memcache operation timeouts
I've had some preliminary success with my own variant of apr_memcache.c (creatively called apr_memcache2.c). Rather than setting the socket timeout, I've been mimicing the timeout strategy I saw in apr_memcache_multgetp, by adding a new helper method: static apr_status_t wait_for_server_or_timeout(apr_pool_t* temp_pool, apr_memcache2_conn_t* conn) { apr_pollset_t* pollset; apr_status_t rv = apr_pollset_create(pollset, 1, temp_pool, 0); if (rv == APR_SUCCESS) { apr_pollfd_t pollfd; pollfd.desc_type = APR_POLL_SOCKET; pollfd.reqevents = APR_POLLIN; pollfd.p = temp_pool; pollfd.desc.s = conn-sock; pollfd.client_data = NULL; apr_pollset_add(pollset, pollfd); apr_int32_t queries_recvd; const apr_pollfd_t* activefds; rv = apr_pollset_poll(pollset, MULT_GET_TIMEOUT, queries_recvd, activefds); if (rv == APR_SUCCESS) { assert(queries_recvd == 1); assert(activefds-desc.s == conn-sock); assert(activefds-client_data == NULL); } } return rv; } And calling that before many of the existing calls to get_server_line as: rv = wait_for_server_or_timeout_no_pool(conn); if (rv != APR_SUCCESS) { ms_release_conn(ms, conn); return rv; } This is just an experiment; I think I can streamline this by pre-populating the pollfd structure as part of the apr_memcache_conn_t (actually now apr_memcache2_conn_t). I have two questions about this: 1. I noticed the version of apr_memcache.c that ships with Apache 2.4 is somewhat different from the one that ships with Apache 2.2. In particular the 2.4 version cannot be compiled against the headers that come with a 2.2 distribution. Is there any downside to taking my hacked 2.2 apr_memcache.c and running it in Apache 2.4? Or should I maintain two hacks? 2. This seems wasteful in terms of system calls. I am making an extra call to poll, rather than relying on the socket timeout. The socket timeout didn't work as well as this though. Does anyone have any theories as to why, or what could be done to the patch in https://issues.apache.org/bugzilla/show_bug.cgi?id=51065 to work? -Josh On Fri, Oct 19, 2012 at 9:25 AM, Joshua Marantz jmara...@google.com wrote: Following up: I tried doing what I suggested above: patching that change into my own copy of apr_memcache.c It was first of all a bad idea to pull in only part of apr_memcache.c because that file changed slightly between 2.2 and 2.4 and our module works in both. I was successful making my own version of apr_memcache (renaming entry-points apr_memcache2*) that I could hack. But if I changed the socket timeout from -1 to 10 seconds, then the system behaved very poorly under load test (though it worked fine in our unit-tests and system-tests). In other words, I think the proposed patch that Jeff pointed to above is not really working (as he predicted). This test was done without SIGSTOPing the memcached; it would timeout under our load anyway and thereafter behave poorly. I'm going to follow up on that bugzilla entry, but for now I'm going to pursue my own complicated mechanism of timing out the calls from my side. -Josh On Thu, Oct 18, 2012 at 10:46 AM, Joshua Marantz jmara...@google.comwrote: Thanks Jeff, that is very helpful. We are considering a course of action and before doing any work toward this, I'd like to understand the pitfalls from people that understand Apache better than us. Here's our reality: we believe we need to incorporate memcached for mod_pagespeed http://modpagespeed.com to scale effectively for very large sites hosting providers. We are fairly close (we think) to releasing this functionality as beta. However, in such large sites, stuff goes wrong: machines crash, power failure, fiber cut, etc. When it does we want to fall back to serving partially unoptimized sites rather than hanging the servers. I understand the realities of backward-compatible APIs. My expectation is that this would take years to make it into an APR distribution we could depend on. We want to deploy this functionality in weeks. The workarounds we have tried backgrounding the apr_memcache calls in a thread and timing out in mainline are complex and even once they work 100% will be very unsatisfactory (resource leaks; Apache refusing to exit cleanly on 'apachectl stop') if this happens more than (say) once a month. Our plan is to copy the patched implementation of apr_memcache_server_connect and the static methods it calls into a new .c file we will link into our module, naming the new entry-point something else (apr_memcache_server_connect_with_timeout seems good). From a CS/SE perspective this is offensive and we admit it, but from a product quality perspective we believe this beats freezes and complicated/imperfect
Re: apr_memcache operation timeouts
Following up: I tried doing what I suggested above: patching that change into my own copy of apr_memcache.c It was first of all a bad idea to pull in only part of apr_memcache.c because that file changed slightly between 2.2 and 2.4 and our module works in both. I was successful making my own version of apr_memcache (renaming entry-points apr_memcache2*) that I could hack. But if I changed the socket timeout from -1 to 10 seconds, then the system behaved very poorly under load test (though it worked fine in our unit-tests and system-tests). In other words, I think the proposed patch that Jeff pointed to above is not really working (as he predicted). This test was done without SIGSTOPing the memcached; it would timeout under our load anyway and thereafter behave poorly. I'm going to follow up on that bugzilla entry, but for now I'm going to pursue my own complicated mechanism of timing out the calls from my side. -Josh On Thu, Oct 18, 2012 at 10:46 AM, Joshua Marantz jmara...@google.comwrote: Thanks Jeff, that is very helpful. We are considering a course of action and before doing any work toward this, I'd like to understand the pitfalls from people that understand Apache better than us. Here's our reality: we believe we need to incorporate memcached for mod_pagespeed http://modpagespeed.com to scale effectively for very large sites hosting providers. We are fairly close (we think) to releasing this functionality as beta. However, in such large sites, stuff goes wrong: machines crash, power failure, fiber cut, etc. When it does we want to fall back to serving partially unoptimized sites rather than hanging the servers. I understand the realities of backward-compatible APIs. My expectation is that this would take years to make it into an APR distribution we could depend on. We want to deploy this functionality in weeks. The workarounds we have tried backgrounding the apr_memcache calls in a thread and timing out in mainline are complex and even once they work 100% will be very unsatisfactory (resource leaks; Apache refusing to exit cleanly on 'apachectl stop') if this happens more than (say) once a month. Our plan is to copy the patched implementation of apr_memcache_server_connect and the static methods it calls into a new .c file we will link into our module, naming the new entry-point something else (apr_memcache_server_connect_with_timeout seems good). From a CS/SE perspective this is offensive and we admit it, but from a product quality perspective we believe this beats freezes and complicated/imperfect workarounds with threads. So I have two questions for the Apache community: 1. What are the practical problems with this approach? Note that in any case a new APR rev would require editing/ifdefing our code anyway, so I think immunity from APR updates such as this patch being applied is not a distinguishing drawback. 2. Is there an example of the correct solution to the technical problem Jeff highlighted: it is apparently missing a call to adjust the socket timeout and to discard the connection if the timeout is reached. That sounds like a pattern that might be found elsewhere in the Apache HTTPD code base. Thanks in advance for your help! -Josh On Wed, Oct 17, 2012 at 8:16 PM, Jeff Trawick traw...@gmail.com wrote: On Wed, Oct 17, 2012 at 3:36 PM, Joshua Marantz jmara...@google.com wrote: Is there a mechanism to time out individual operations? No, the socket connect timeout is hard-coded at 1 second and the socket I/O timeout is disabled. Bugzilla bug https://issues.apache.org/bugzilla/show_bug.cgi?id=51065 has a patch, though it is apparently missing a call to adjust the socket timeout and to discard the connection if the timeout is reached. More importantly, the API can only be changed in future APR 2.0; alternate, backwards-compatible API(s) could be added in future APR-Util 1.6. If memcached freezes, then it appears my calls to 'get' will block until memcached wakes up. Is there any way to set a timeout for that call? I can repro this in my unit tests by sending a SIGSTOP to memcached before doing a 'get'? Here are my observations: apr_memcache_multgetp seems to time out in bounded time if I SIGSTOP the memcached process. Yes! apr_memcache_getp seems to hang indefinitely if I SIGSTOP the memcached process. apr_memcache_set seems to hang indefinitely if I SIGSTOP the memcached process. apr_memcache_delete seems to hang indefinitely if I SIGSTOP the memcached process. apr_memcache_stats seems to hang indefinitely if I SIGSTOP the memcached process. That last one really sucks as I am using that to print the status of all my cache shards to the log file if I detected a problem :( Why does apr_memcache_multgetp do what I want and not the others? Can I induce the others to have reasonable timeout behavior? When I SIGSTOP
apr_memcache operation timeouts
Is there a mechanism to time out individual operations? If memcached freezes, then it appears my calls to 'get' will block until memcached wakes up. Is there any way to set a timeout for that call? I can repro this in my unit tests by sending a SIGSTOP to memcached before doing a 'get'? Here are my observations: apr_memcache_multgetp seems to time out in bounded time if I SIGSTOP the memcached process. Yes! apr_memcache_getp seems to hang indefinitely if I SIGSTOP the memcached process. apr_memcache_set seems to hang indefinitely if I SIGSTOP the memcached process. apr_memcache_delete seems to hang indefinitely if I SIGSTOP the memcached process. apr_memcache_stats seems to hang indefinitely if I SIGSTOP the memcached process. That last one really sucks as I am using that to print the status of all my cache shards to the log file if I detected a problem :( Why does apr_memcache_multgetp do what I want and not the others? Can I induce the others to have reasonable timeout behavior? When I SIGSTOP memcached this makes it hard to even restart Apache, at least with graceful-stop. On a related note, the apr_memcache documentationhttp://apr.apache.org/docs/apr-util/1.4/group___a_p_r___util___m_c.htmlis very thin. I'd be happy to augment it with my observations on its usage and the meaning of some of the arguments if that was desired. How would I go about that? -Josh
Re: aprmemcache question
Now that we've established that the TTL passed into the server-create call is for reaping idle connections and not individual operation timeouts, I want to ask about timing out individual operations. If memcached freezes, then it appears my calls to 'get' will block until memcached wakes up. Is there any way to set a timeout for that call? I can repro this in my unit tests by sending a SIGSTOP to memcached before doing a 'get'. -Josh On Thu, Sep 27, 2012 at 4:37 PM, Joshua Marantz jmara...@google.com wrote: This helps a lot. I think 600 seconds seems like a fine idle-reap timeout. I need to investigate why some lookups take a second or more. Maybe there's a mutex contention on my end somewhere. Thanks! -Josh On Thu, Sep 27, 2012 at 2:08 PM, Jeff Trawick traw...@gmail.com wrote: On Thu, Sep 27, 2012 at 1:55 PM, Joshua Marantz jmara...@google.com wrote: That one call-site is HTTP_24/src/modules/cache/mod_socache_memcache.c, right? That was where I stole my args from. no, subversion As the TCP/IP layer is a lower level abstraction than bathe apr_memcache interface, I'm still not clear on exactly what that means. Does a value of 600 mean that a single multiget must complete in 600 microseconds otherwise it fails with APR_TIMEUP? ttl only affects connections which are not currently used; it does not control I/O timeouts That might explain the behavior I saw. I've now jacked that up by x1e6 to 600 seconds and I don't see timeouts, but I'm hoping someone can bridge the gap between the socket-level explanation and the apr_memcache API call. I was assuming that apr_memcache created the TCP/IP connection when I called apr_memcache_server_create, and there even 600 seconds seems too short. Is the functionality more like it will create connections on-demand and leave them running for N microseconds, re-using the connection for multiple requests until TTL microseconds have elapsed since creation? create on demand reuse existing idle connections when possible when performing maintenance on the idle connections, clean up any which were idle for N microseconds If a connection is always reused before it is idle for N microseconds, it will live as long as memcached allows. If that's the case then I guess that every 10 minutes one of my cache lookups may have high latency to re-establish the connection, is that right? I've been histogramming this under load and seeing some long tail requests with very high latency. My median latency is only 143us which is great. My 90%, 95% and 99% are all around 5ms, which is fine as well. But I've got a fairly significant number of long-tail lookups that take hundreds of ms or even seconds to finish, and one crazy theory is that this is all reconnect cost. It would be nice if the TTL were interpreted as a maximum idle time before the connection is reaped, rather than stuttering response-time on a very active channel. It is. The ttl is interpreted by the reslist layer, which won't touch objects until they're returned to the list. This testing is all using a single memcached running on localhost. -Josh On Thu, Sep 27, 2012 at 11:24 AM, Jeff Trawick traw...@gmail.com wrote: On Thu, Sep 27, 2012 at 11:15 AM, Joshua Marantz jmara...@google.com wrote: On Thu, Sep 27, 2012 at 10:58 AM, Ben Noordhuis i...@bnoordhuis.nl wrote: If dlsym() is called with the special handle NULL, it is interpreted as a reference to the executable or shared object from which the call is being made. Thus a shared object can reference its own symbols. And that's how it works on Linux, Solaris, NetBSD and probably OpenBSD as well. Cool, thanks. Do you have a feel for the exact meaning of that TTL parameter to apr_memcache_server_create? You mean what units it uses? Microseconds (at least, in 2.4). Actually what I meant was what that value is used for in the library. The phrase time to live of client connection confuses me. Does it really mean the maximum number of seconds apr_memcache is willing to wait for a single operation? Or does it mean *both*, implying that a fresh TCP/IP connection is made for every new operation, but will stay alive for only a certain number of seconds. TCP/IP connections, once created, will be retained for the specified (ttl) number of seconds. They'll be created when needed. The socket connect timeout is hard-coded to 1 second, and there's no timeout for I/O. It is a little disturbing from a module-developer perspective to have the meaning of that parameter change by a factor of 1M between versions. Would it be better to revert the recent change and instead change the doc to match the current behavior? The doc was already changed to match the behavior, but I missed that. The caller I know
Re: aprmemcache question
Thanks Ben, That might be an interesting hack to try, although I wonder whether some of our friends running mod_pagespeed on FreeBSD might run into trouble with it. I did confirm that my prefork build has APR built with APR_HAS_THREADS, which for some reason I had earlier thought was not the case. Do you have a feel for the exact meaning of that TTL parameter to apr_memcache_server_create? -Josh On Thu, Sep 27, 2012 at 8:53 AM, Ben Noordhuis i...@bnoordhuis.nl wrote: On Thu, Sep 27, 2012 at 4:05 AM, Joshua Marantz jmara...@google.com wrote: RE failing the build of my module -- the dominant usage is via precompiled binaries we supply. Is there an apr query for determining whether apr was compiled with threads I could do on startup? I don't think there's an official way but you know apr was compiled with APR_HAS_THREADS when dlsym(NULL, apr_os_thread_current) != NULL. Using dlsym() like that is not quite compatible with POSIX but it works on all the major Unices.
Re: aprmemcache question
On Thu, Sep 27, 2012 at 10:58 AM, Ben Noordhuis i...@bnoordhuis.nl wrote: If dlsym() is called with the special handle NULL, it is interpreted as a reference to the executable or shared object from which the call is being made. Thus a shared object can reference its own symbols. And that's how it works on Linux, Solaris, NetBSD and probably OpenBSD as well. Cool, thanks. Do you have a feel for the exact meaning of that TTL parameter to apr_memcache_server_create? You mean what units it uses? Microseconds (at least, in 2.4). Actually what I meant was what that value is used for in the library. The phrase time to live of client connection confuses me. Does it really mean the maximum number of seconds apr_memcache is willing to wait for a single operation? Or does it mean *both*, implying that a fresh TCP/IP connection is made for every new operation, but will stay alive for only a certain number of seconds. It is a little disturbing from a module-developer perspective to have the meaning of that parameter change by a factor of 1M between versions. Would it be better to revert the recent change and instead change the doc to match the current behavior? -Josh
Re: aprmemcache question
This helps a lot. I think 600 seconds seems like a fine idle-reap timeout. I need to investigate why some lookups take a second or more. Maybe there's a mutex contention on my end somewhere. Thanks! -Josh On Thu, Sep 27, 2012 at 2:08 PM, Jeff Trawick traw...@gmail.com wrote: On Thu, Sep 27, 2012 at 1:55 PM, Joshua Marantz jmara...@google.com wrote: That one call-site is HTTP_24/src/modules/cache/mod_socache_memcache.c, right? That was where I stole my args from. no, subversion As the TCP/IP layer is a lower level abstraction than bathe apr_memcache interface, I'm still not clear on exactly what that means. Does a value of 600 mean that a single multiget must complete in 600 microseconds otherwise it fails with APR_TIMEUP? ttl only affects connections which are not currently used; it does not control I/O timeouts That might explain the behavior I saw. I've now jacked that up by x1e6 to 600 seconds and I don't see timeouts, but I'm hoping someone can bridge the gap between the socket-level explanation and the apr_memcache API call. I was assuming that apr_memcache created the TCP/IP connection when I called apr_memcache_server_create, and there even 600 seconds seems too short. Is the functionality more like it will create connections on-demand and leave them running for N microseconds, re-using the connection for multiple requests until TTL microseconds have elapsed since creation? create on demand reuse existing idle connections when possible when performing maintenance on the idle connections, clean up any which were idle for N microseconds If a connection is always reused before it is idle for N microseconds, it will live as long as memcached allows. If that's the case then I guess that every 10 minutes one of my cache lookups may have high latency to re-establish the connection, is that right? I've been histogramming this under load and seeing some long tail requests with very high latency. My median latency is only 143us which is great. My 90%, 95% and 99% are all around 5ms, which is fine as well. But I've got a fairly significant number of long-tail lookups that take hundreds of ms or even seconds to finish, and one crazy theory is that this is all reconnect cost. It would be nice if the TTL were interpreted as a maximum idle time before the connection is reaped, rather than stuttering response-time on a very active channel. It is. The ttl is interpreted by the reslist layer, which won't touch objects until they're returned to the list. This testing is all using a single memcached running on localhost. -Josh On Thu, Sep 27, 2012 at 11:24 AM, Jeff Trawick traw...@gmail.com wrote: On Thu, Sep 27, 2012 at 11:15 AM, Joshua Marantz jmara...@google.com wrote: On Thu, Sep 27, 2012 at 10:58 AM, Ben Noordhuis i...@bnoordhuis.nl wrote: If dlsym() is called with the special handle NULL, it is interpreted as a reference to the executable or shared object from which the call is being made. Thus a shared object can reference its own symbols. And that's how it works on Linux, Solaris, NetBSD and probably OpenBSD as well. Cool, thanks. Do you have a feel for the exact meaning of that TTL parameter to apr_memcache_server_create? You mean what units it uses? Microseconds (at least, in 2.4). Actually what I meant was what that value is used for in the library. The phrase time to live of client connection confuses me. Does it really mean the maximum number of seconds apr_memcache is willing to wait for a single operation? Or does it mean *both*, implying that a fresh TCP/IP connection is made for every new operation, but will stay alive for only a certain number of seconds. TCP/IP connections, once created, will be retained for the specified (ttl) number of seconds. They'll be created when needed. The socket connect timeout is hard-coded to 1 second, and there's no timeout for I/O. It is a little disturbing from a module-developer perspective to have the meaning of that parameter change by a factor of 1M between versions. Would it be better to revert the recent change and instead change the doc to match the current behavior? The doc was already changed to match the behavior, but I missed that. The caller I know of used the wrong unit, and I'll submit a patch to fix that in the caller, as well as revert my screw-up from yesterday. -Josh -- Born in Roswell... married an alien... http://emptyhammock.com/ -- Born in Roswell... married an alien... http://emptyhammock.com/
aprmemcache question
Hi, I've been having some success with the apr_memcache_* functions. In load-tests, however, I'm finding a lot of timeouts with apr_memcache_multgetp. Specifically, the status returned with the individual elements is APR_TIMEUP. This leads me to wonder what the significance of the second to last arg to this function is: apr_memcache_server_create( pool_, hosts_[i].c_str(), ports_[i], kDefaultServerMin, kDefaultServerSmax, thread_limit_, kDefaultServerTtlUs, server); I have kDefaultServerSmax initialized to 600, as that's the value I found in mod_socache_memcache.c But that seems stingy (if it's really in microseconds). Should I be giving that a few hundred millis instead? http://apr.apache.org/docs/apr-util/1.4/group___a_p_r___util___m_c.html#ga18ddd72bc1ab5edb0a08a8f26f193bd3 claims that means time to live of client connection but I don't understand what that phrase means exactly, or if it relates to the APR_TIMEUP returns I've been suffering from. My code is here; http://code.google.com/p/modpagespeed/source/browse/trunk/src/net/instaweb/apache/apr_mem_cache.cc -Josh
Re: aprmemcache question
+dev (sorry for the duplicate; my first attempt failed due to not being a subscriber). Keeping modules-dev on CC if that's appropriate. Thanks, Jeff, I was wondering if there was a units issue there. I'm still wondering if anyone can describe the meaning of that argument in more detail. Is that related to my multiget APR_TIMEUP returns? The phrase time to live of client connection confuses me. Would it be inaccurate to instead say the maximum number of seconds apr_memcache is willing to wait for a single operation? Or does it mean *both*, implying that a fresh TCP/IP connection is made for every new operation, but will stay alive for only a certain number of seconds. I have a practical question about how I release software given this change. Our module (mod_pagespeed) is documented to run with Apache 2.2 and Apache 2.4. It seems like for 2.2 I should probably multiple my desired argument by a million. Same with for 2.4.x and earlier, for some value of x. How should I work this in my code? Should I query the version number using an apr utility or something and multiply by a million in certain cases? What's the best practice calling this function for module developers? -Josh On Wed, Sep 26, 2012 at 6:20 PM, Jeff Trawick traw...@gmail.com wrote: On Wed, Sep 26, 2012 at 5:38 PM, Joshua Marantz jmara...@google.com wrote: Hi, I've been having some success with the apr_memcache_* functions. In load-tests, however, I'm finding a lot of timeouts with apr_memcache_multgetp. Specifically, the status returned with the individual elements is APR_TIMEUP. This leads me to wonder what the significance of the second to last arg to this function is: apr_memcache_server_create( pool_, hosts_[i].c_str(), ports_[i], kDefaultServerMin, kDefaultServerSmax, thread_limit_, kDefaultServerTtlUs, server); I have kDefaultServerSmax initialized to 600, as that's the value I found in mod_socache_memcache.c But that seems stingy (if it's really in microseconds). Should I be giving that a few hundred millis instead? http://apr.apache.org/docs/apr-util/1.4/group___a_p_r___util___m_c.html#ga18ddd72bc1ab5edb0a08a8f26f193bd3 claims that means time to live of client connection but I don't understand what that phrase means exactly, or if it relates to the APR_TIMEUP returns I've been suffering from. My code is here; http://code.google.com/p/modpagespeed/source/browse/trunk/src/net/instaweb/apache/apr_mem_cache.cc -Josh d...@apr.apache.org is a better place to ask about details of apr functions. Coincidentally, earlier today I committed someone's fix for the confusion about the units of ttl: http://svn.apache.org/viewvc?view=revisionrevision=1390530 It is supposed to be in seconds. Pick up the tiny change to apr_memcache.c and see if that helps anything. You should continue this discussion on d...@apr.apache.org. -- Born in Roswell... married an alien... http://emptyhammock.com/
Re: aprmemcache question
Looking at source, I see that Jeff's patch, and the 'ttl' parameter in general, is only referenced under '#if APR_HAS_THREADS'. When I load-tested and found the timeouts, I was testing under Apache 2.2 Prefork, and thus that patched code is not even compiled, IIUC. However I would still like to know what that parameter is for when running under Worker. I think the implication of my source journey is also that if my module instantiates multiple threads under Prefork (which it does), it must call apr_memcache* routines from only one of them. Is that correct? -Josh On Wed, Sep 26, 2012 at 7:17 PM, Joshua Marantz jmara...@google.com wrote: +dev (sorry for the duplicate; my first attempt failed due to not being a subscriber). Keeping modules-dev on CC if that's appropriate. Thanks, Jeff, I was wondering if there was a units issue there. I'm still wondering if anyone can describe the meaning of that argument in more detail. Is that related to my multiget APR_TIMEUP returns? The phrase time to live of client connection confuses me. Would it be inaccurate to instead say the maximum number of seconds apr_memcache is willing to wait for a single operation? Or does it mean *both*, implying that a fresh TCP/IP connection is made for every new operation, but will stay alive for only a certain number of seconds. I have a practical question about how I release software given this change. Our module (mod_pagespeed) is documented to run with Apache 2.2 and Apache 2.4. It seems like for 2.2 I should probably multiple my desired argument by a million. Same with for 2.4.x and earlier, for some value of x. How should I work this in my code? Should I query the version number using an apr utility or something and multiply by a million in certain cases? What's the best practice calling this function for module developers? -Josh On Wed, Sep 26, 2012 at 6:20 PM, Jeff Trawick traw...@gmail.com wrote: On Wed, Sep 26, 2012 at 5:38 PM, Joshua Marantz jmara...@google.com wrote: Hi, I've been having some success with the apr_memcache_* functions. In load-tests, however, I'm finding a lot of timeouts with apr_memcache_multgetp. Specifically, the status returned with the individual elements is APR_TIMEUP. This leads me to wonder what the significance of the second to last arg to this function is: apr_memcache_server_create( pool_, hosts_[i].c_str(), ports_[i], kDefaultServerMin, kDefaultServerSmax, thread_limit_, kDefaultServerTtlUs, server); I have kDefaultServerSmax initialized to 600, as that's the value I found in mod_socache_memcache.c But that seems stingy (if it's really in microseconds). Should I be giving that a few hundred millis instead? http://apr.apache.org/docs/apr-util/1.4/group___a_p_r___util___m_c.html#ga18ddd72bc1ab5edb0a08a8f26f193bd3 claims that means time to live of client connection but I don't understand what that phrase means exactly, or if it relates to the APR_TIMEUP returns I've been suffering from. My code is here; http://code.google.com/p/modpagespeed/source/browse/trunk/src/net/instaweb/apache/apr_mem_cache.cc -Josh d...@apr.apache.org is a better place to ask about details of apr functions. Coincidentally, earlier today I committed someone's fix for the confusion about the units of ttl: http://svn.apache.org/viewvc?view=revisionrevision=1390530 It is supposed to be in seconds. Pick up the tiny change to apr_memcache.c and see if that helps anything. You should continue this discussion on d...@apr.apache.org. -- Born in Roswell... married an alien... http://emptyhammock.com/
Re: aprmemcache question
RE failing the build of my module -- the dominant usage is via precompiled binaries we supply. Is there an apr query for determining whether apr was compiled with threads I could do on startup? -Josh On Wed, Sep 26, 2012 at 7:40 PM, Jeff Trawick traw...@gmail.com wrote: On Wed, Sep 26, 2012 at 7:31 PM, Joshua Marantz jmara...@google.com wrote: Looking at source, I see that Jeff's patch, and the 'ttl' parameter in general, is only referenced under '#if APR_HAS_THREADS'. When I load-tested and found the timeouts, I was testing under Apache 2.2 Prefork, and thus that patched code is not even compiled, IIUC. However I would still like to know what that parameter is for when running under Worker. I think the implication of my source journey is also that if my module instantiates multiple threads under Prefork (which it does), it must call apr_memcache* routines from only one of them. Is that correct? APR is usually compiled with thread support even when using the prefork MPM. Check APR_HAS_THREADS in apr.h. If APR_HAS_THREADS is 0 (very unlikely), you probably want to fail the build of your module to avoid having to worry about this. As far as what the parameter means... I'll try to look tomorrow if nobody replies first. See apu_version() for the APR-util version. -Josh On Wed, Sep 26, 2012 at 7:17 PM, Joshua Marantz jmara...@google.com wrote: +dev (sorry for the duplicate; my first attempt failed due to not being a subscriber). Keeping modules-dev on CC if that's appropriate. Thanks, Jeff, I was wondering if there was a units issue there. I'm still wondering if anyone can describe the meaning of that argument in more detail. Is that related to my multiget APR_TIMEUP returns? The phrase time to live of client connection confuses me. Would it be inaccurate to instead say the maximum number of seconds apr_memcache is willing to wait for a single operation? Or does it mean *both*, implying that a fresh TCP/IP connection is made for every new operation, but will stay alive for only a certain number of seconds. I have a practical question about how I release software given this change. Our module (mod_pagespeed) is documented to run with Apache 2.2 and Apache 2.4. It seems like for 2.2 I should probably multiple my desired argument by a million. Same with for 2.4.x and earlier, for some value of x. How should I work this in my code? Should I query the version number using an apr utility or something and multiply by a million in certain cases? What's the best practice calling this function for module developers? -Josh On Wed, Sep 26, 2012 at 6:20 PM, Jeff Trawick traw...@gmail.com wrote: On Wed, Sep 26, 2012 at 5:38 PM, Joshua Marantz jmara...@google.com wrote: Hi, I've been having some success with the apr_memcache_* functions. In load-tests, however, I'm finding a lot of timeouts with apr_memcache_multgetp. Specifically, the status returned with the individual elements is APR_TIMEUP. This leads me to wonder what the significance of the second to last arg to this function is: apr_memcache_server_create( pool_, hosts_[i].c_str(), ports_[i], kDefaultServerMin, kDefaultServerSmax, thread_limit_, kDefaultServerTtlUs, server); I have kDefaultServerSmax initialized to 600, as that's the value I found in mod_socache_memcache.c But that seems stingy (if it's really in microseconds). Should I be giving that a few hundred millis instead? http://apr.apache.org/docs/apr-util/1.4/group___a_p_r___util___m_c.html#ga18ddd72bc1ab5edb0a08a8f26f193bd3 claims that means time to live of client connection but I don't understand what that phrase means exactly, or if it relates to the APR_TIMEUP returns I've been suffering from. My code is here; http://code.google.com/p/modpagespeed/source/browse/trunk/src/net/instaweb/apache/apr_mem_cache.cc -Josh d...@apr.apache.org is a better place to ask about details of apr functions. Coincidentally, earlier today I committed someone's fix for the confusion about the units of ttl: http://svn.apache.org/viewvc?view=revisionrevision=1390530 It is supposed to be in seconds. Pick up the tiny change to apr_memcache.c and see if that helps anything. You should continue this discussion on d...@apr.apache.org. -- Born in Roswell... married an alien... http://emptyhammock.com/ -- Born in Roswell... married an alien... http://emptyhammock.com/
Re: apr_memcache vs libmemcached
Following up: I've been pretty successful using apr_memcache so far. The performance is roughly on par with a file-cache running on a tmpfs partition, but of course it adds network scalability. I'd encourage anyone wanting to integrate memcached into Apache modules to give it a try. It might even be one of the easiest ways to get a map that can be used across processes on a single server, rather than working with shared memory. It *looks* like libmemcached has a richer API and the potential for better performance due to asynchronous APIs and usage of the memcached binary protocol, but I have not been as successful with it. And apr_memcache seems good enough, performance wise, based on my load tests, and so far it's very stable. Example usage: http://code.google.com/p/modpagespeed/source/browse/trunk/src/net/instaweb/apache/apr_mem_cache.cc, .hhttp://code.google.com/p/modpagespeed/source/browse/trunk/src/net/instaweb/apache/apr_mem_cache.h, and _test.cchttp://code.google.com/p/modpagespeed/source/browse/trunk/src/net/instaweb/apache/apr_mem_cache_test.cc . -Josh On Thu, Jul 19, 2012 at 5:47 PM, Joshua Marantz jmara...@google.com wrote: I think the point of that Wiki was that whoever wrote that entry claimed that apr_memcached wasn't being actively worked on, but perhaps that's false. I don't think the implication was that the work was expected to happen in code.google.com. This question is in the context of mod_pagespeedhttps://developers.google.com/speed/pagespeed/mod, which currently uses the file system for caching that's visible across Apache child processes. That works pretty well but has limitations in performance and network scope. memcached is being considered as a possible replacement for that. I'll take a look at socache. One of the advantages of libmemcached is that it supports -- or claims to support -- asynchronous fetches, which we believe is important for performance at scale. However, I have not actually been able to get that to work as expected, and have fallen back to a fairly synchronous model. The libmemcached API *looks* asynchronous -- it just doesn't seem to quite work. And if I'm going to stay synchronous then it might be a lot easier to integrate if I use the built in APR support. And even synchronous fetches from memcached might be better than synchronous reads form disk. Thanks, -Josh On Thu, Jul 19, 2012 at 5:39 PM, Nick Kew n...@apache.org wrote: On Thu, 19 Jul 2012 16:41:51 -0400 Joshua Marantz jmara...@google.com wrote: Hi, Is anyone maintaining apr_memcache? Or should I stick with libmemcached? This page: http://code.google.com/p/memcached/wiki/Clients suggests apr_memcached is not maintained. Huh? It's not maintained at google code since it was contributed to the core APR project. If you have any reasonably recent APR installed (as you must have if you run httpd), it includes apr_memcache. Since you posted here I'd guess your purpose is writing a module? You might want to look at the socache modules as a higher-level abstraction. -- Nick Kew
apr_memcache vs libmemcached
Hi, Is anyone maintaining apr_memcache? Or should I stick with libmemcached? This page: http://code.google.com/p/memcached/wiki/Clients suggests apr_memcached is not maintained. Thanks! -Josh
Re: apr_memcache vs libmemcached
I think the point of that Wiki was that whoever wrote that entry claimed that apr_memcached wasn't being actively worked on, but perhaps that's false. I don't think the implication was that the work was expected to happen in code.google.com. This question is in the context of mod_pagespeedhttps://developers.google.com/speed/pagespeed/mod, which currently uses the file system for caching that's visible across Apache child processes. That works pretty well but has limitations in performance and network scope. memcached is being considered as a possible replacement for that. I'll take a look at socache. One of the advantages of libmemcached is that it supports -- or claims to support -- asynchronous fetches, which we believe is important for performance at scale. However, I have not actually been able to get that to work as expected, and have fallen back to a fairly synchronous model. The libmemcached API *looks* asynchronous -- it just doesn't seem to quite work. And if I'm going to stay synchronous then it might be a lot easier to integrate if I use the built in APR support. And even synchronous fetches from memcached might be better than synchronous reads form disk. Thanks, -Josh On Thu, Jul 19, 2012 at 5:39 PM, Nick Kew n...@apache.org wrote: On Thu, 19 Jul 2012 16:41:51 -0400 Joshua Marantz jmara...@google.com wrote: Hi, Is anyone maintaining apr_memcache? Or should I stick with libmemcached? This page: http://code.google.com/p/memcached/wiki/Clients suggests apr_memcached is not maintained. Huh? It's not maintained at google code since it was contributed to the core APR project. If you have any reasonably recent APR installed (as you must have if you run httpd), it includes apr_memcache. Since you posted here I'd guess your purpose is writing a module? You might want to look at the socache modules as a higher-level abstraction. -- Nick Kew
Re: Get the directory of the module
I think he wants to write bytecodes during module installation when he will have write access. During installation can you also write a .conf template showing your module where the bytecodes are? Josh On Jun 11, 2012 7:29 PM, Jerry Stuckle je...@smartechhomes.com wrote: On 6/11/2012 5:49 PM, Ben Noordhuis wrote: On Mon, Jun 11, 2012 at 10:10 PM, Bart Wiegmansbartwiegmans@gmail.**combartwiegm...@gmail.com wrote: Hello everybody, For a project I'm doing, I need to install a few bytecode files alongside my module. I was planning on placing them in the modules directory but I realised that at runtime I do not know where that is. What is more, that directory may (and will, as a matter of fact) vary during installation and testing. But most importantly, the server knows where the module is kept as it specified by LoadModule. So in short, how can I determine the directory of my module at runtime? You can't, the file path is internal to mod_so.c. I don't think it even stores it. In addition, there is no guarantee you have write access to that directory.
Re: Get the directory of the module
I think we are saying the same thing, right? To tell his module I'm suggesting he write the path where the .so is installed into his .conf file so that he can get the path at runtime. On Mon, Jun 11, 2012 at 8:02 PM, Jerry Stuckle je...@smartechhomes.comwrote: In that case he should also be able to tell his module where the files are. On 6/11/2012 7:40 PM, Joshua Marantz wrote: I think he wants to write bytecodes during module installation when he will have write access. During installation can you also write a .conf template showing your module where the bytecodes are? Josh On Jun 11, 2012 7:29 PM, Jerry Stucklejerry@smartechhomes.**comje...@smartechhomes.com wrote: On 6/11/2012 5:49 PM, Ben Noordhuis wrote: On Mon, Jun 11, 2012 at 10:10 PM, Bart Wiegmansbartwiegmans@gmail. combartwiegm...@gmail.com wrote: Hello everybody, For a project I'm doing, I need to install a few bytecode files alongside my module. I was planning on placing them in the modules directory but I realised that at runtime I do not know where that is. What is more, that directory may (and will, as a matter of fact) vary during installation and testing. But most importantly, the server knows where the module is kept as it specified by LoadModule. So in short, how can I determine the directory of my module at runtime? You can't, the file path is internal to mod_so.c. I don't think it even stores it. In addition, there is no guarantee you have write access to that directory.
Re: Determining mimetype of document
In understand any module *can* set content-type late: I'm just wondering if that happens with any frequency. E.g.when I googled for how to set content-type in Apache, I got references to AddType and some hacks using mod_rewrite, both of which would run upstream of my filter. My main concern is mod_headers since it runs downstream. RE firefox sniffing content-type: does that imply that if there is an explicit mimetype it will ignore it and determine XHTML vs HTML via sniffing, I suppose, for DOCTYPE? Do you have a link to that bit of news? That certainly complicates things. -Josh On Fri, Jun 8, 2012 at 5:16 PM, Joe Lewis j...@joe-lewis.com wrote: On 06/08/2012 03:07 PM, Joshua Marantz wrote: Hi, I'm trying to figure out whether my filter, which currently runs upstream of mod_headers, is likely to see the correct mimetype in request-content_type. In particular, we need to know whether browsers will interpret the content as XHTML or HTML, which is determined by the mimetype. Do people typically set the mimetype using mod_headers, or is that typically set using AddType or some other mechanism? It's usually set by the content generator. However, you have to keep in mind that any module may modify that value (any output filter may, too) up until the AP_FTYPE_CONTENT_SET (runs after the AP_FTYPE_RESOURCE output filters). Additionally, please keep in mind that Firefox has begun the old I.E. hack of sniffing the content and ignoring the Content-Type header if it can figure it out, so you will have to be aware that content_type is not indicative at any stage of what the browser is going to do. Joe -- http://www.silverhawk.net/
Re: output filter ordering question: mod_deflate vs mod_headers vs mod_pagespeed
Thanks for the quick reply, Nick. I played around with this idea but couldn't get it to work. My filter now runs at AP_FTYPE_CONTENT_SET + 1, to make sure it runs after mod_headers. I don't know how to try to coax mod_deflate to run after me. I can prevent it from running before me by removing it from the filter-chain in before my main filter-function runs, but when I try to then put it back in the filter chain after my main filter function, it doesn't appear to work. But you are right; this is a hack on a hack and perhaps not worth pursuing further. Is mod_filter a mechanism I could use in Apache 2.2 to accomplish what I need? I found http://httpd.apache.org/docs/2.2/mod/mod_filter.html and it looks promising. I'll give it a try. The tone of your email made it sound like mod_filter is not quite ready, but it's there in my distribution. Can you elaborate on the state of mod_filter? Thanks! -Josh On Thu, May 17, 2012 at 2:30 AM, Nick Kew n...@apache.org wrote: On 17 May 2012, at 04:24, Joshua Marantz wrote: Or is that insane /or dangerous? AP_FTYPE_ values are something of a blunt instrument, not ideal for cases where you care about ordering. Running mod_headers as a filter is a bit of a hack. What you're proposing is kind-of building a hack onto a hack. I'm sure you can make it work (at least in controlled circumstances where you're not competing against other similar fudges) but IMHO you're right to be worried. Having once upon a time written mod_filter to deal with more complex configuration than the original design envisaged, I wonder if your issue might be a hint that we should revisit the API for programmatic configuration, and make your proposal less hackish? -- Nick Kew
Re: output filter ordering question: mod_deflate vs mod_headers vs mod_pagespeed
Hi I gave it a try but need a little help to get further. I added this to my configuration file: FilterDeclare headers CONTENT_SET FilterDeclare pagespeed CONTENT_SET FilterDeclare deflate CONTENT_SET FilterProvider pagespeed MOD_PAGESPEED_OUTPUT_FILTER resp=Content-Type $text/html FilterProvider headers FIXUP_HEADERS_OUT resp=Content-Type $text/html FilterProvider deflate DEFLATE resp=Content-Type $text/html FilterChain headers pagespeed deflate However when I look at the request in an early output-filter I see this: pagespeed: AP_FTYPE_CONTENT_SET(0) deflate: AP_FTYPE_CONTENT_SET(0) fixup_headers_out: AP_FTYPE_CONTENT_SET(0) byterange: AP_FTYPE_PROTOCOL(0) content_length: AP_FTYPE_PROTOCOL(0) http_header: AP_FTYPE_PROTOCOL(0) http_outerror: AP_FTYPE_PROTOCOL(0) log_input_output: AP_FTYPE_NETWORK(-1) core: AP_FTYPE_NETWORK(0) The code that printed this is: void PrintFilterChain(ap_filter_t* filter) { // TODO(jmarantz): debug-check that these are in increasing order. static ap_filter_type types[] = { AP_FTYPE_RESOURCE, AP_FTYPE_CONTENT_SET, AP_FTYPE_PROTOCOL, AP_FTYPE_TRANSCODE, AP_FTYPE_CONNECTION, AP_FTYPE_NETWORK }; static const char* type_names[] = { AP_FTYPE_RESOURCE, AP_FTYPE_CONTENT_SET, AP_FTYPE_PROTOCOL, AP_FTYPE_TRANSCODE, AP_FTYPE_CONNECTION, AP_FTYPE_NETWORK, END }; static ap_filter_type* types_end = types + arraysize(types); for (ap_filter_t* next; filter != NULL; filter = next) { next = filter-next; // Get the symbolic name for the filter's position, relative to the // symbolic constants above. ap_filter_rec_t* frec = filter-frec; ap_filter_type type = frec-ftype; ap_filter_type* pos = std::lower_bound(types, types_end, type); int index = pos - types; int delta = static_castint(type) - static_castint(*pos); fprintf(stdout, %s: %s(%d)\n, frec-name, type_names[index], delta); } fflush(stdout); } Is the filter -next chain not the correct way to look at this data? In any case the evidence from my system-tests suggest that I haven't achieved the ordering I want yet. Is there something else I need to do? On Thu, May 17, 2012 at 9:27 AM, Joshua Marantz jmara...@google.com wrote: Thanks for the quick reply, Nick. I played around with this idea but couldn't get it to work. My filter now runs at AP_FTYPE_CONTENT_SET + 1, to make sure it runs after mod_headers. I don't know how to try to coax mod_deflate to run after me. I can prevent it from running before me by removing it from the filter-chain in before my main filter-function runs, but when I try to then put it back in the filter chain after my main filter function, it doesn't appear to work. But you are right; this is a hack on a hack and perhaps not worth pursuing further. Is mod_filter a mechanism I could use in Apache 2.2 to accomplish what I need? I found http://httpd.apache.org/docs/2.2/mod/mod_filter.html and it looks promising. I'll give it a try. The tone of your email made it sound like mod_filter is not quite ready, but it's there in my distribution. Can you elaborate on the state of mod_filter? Thanks! -Josh On Thu, May 17, 2012 at 2:30 AM, Nick Kew n...@apache.org wrote: On 17 May 2012, at 04:24, Joshua Marantz wrote: Or is that insane /or dangerous? AP_FTYPE_ values are something of a blunt instrument, not ideal for cases where you care about ordering. Running mod_headers as a filter is a bit of a hack. What you're proposing is kind-of building a hack onto a hack. I'm sure you can make it work (at least in controlled circumstances where you're not competing against other similar fudges) but IMHO you're right to be worried. Having once upon a time written mod_filter to deal with more complex configuration than the original design envisaged, I wonder if your issue might be a hint that we should revisit the API for programmatic configuration, and make your proposal less hackish? -- Nick Kew
output filter ordering question: mod_deflate vs mod_headers vs mod_pagespeed
Hi, Currently, mod_pagespeed http://code.google.com/p/modpagespeed/ runs before mod_headers by registering as: ap_register_output_filter( kModPagespeedFilterName, instaweb_out_filter, NULL, static_castap_filter_type(AP_FTYPE_RESOURCE + 1)); mod_headers registers with: ap_register_output_filter(FIXUP_HEADERS_OUT, ap_headers_output_filter, NULL, AP_FTYPE_CONTENT_SET); with: ./include/util_filter.h:AP_FTYPE_RESOURCE = 10, ./include/util_filter.h:AP_FTYPE_CONTENT_SET = 20, We've been accumulating some motivation to run *after* mod_headers, rather than *before*. The reason is that mod_pagespeed currently has to rewrite content without knowing the resolved content-type based on the Headers directives in the user's configuration files. In particular, we don't really know definitively whether browsers will treat content as XHTML or HTML without seeing the accurate content-type. We can do parse the DOCTYPE if there is one, but that's not really the Source Of Truth as far as browsers are concerned: the mimetype is. Unfortunately, mod_deflate.c is also registered at AP_FTYPE_CONTENT_SET: ap_register_output_filter(deflateFilterName, deflate_out_filter, NULL, AP_FTYPE_CONTENT_SET); mod_pagespeed really needs to run before mod_deflate. mod_pagespeed needs HTML in the clear, and we don't want to spend CPU-cycles re-inflating what mod_deflate just shrunk. But I'm at a loss to understand what dictates the order between mod_headers and mod_deflate. They are registered at the same position. Is it just that they don't really care which position they run at? Is there anything sane that mod_pagespeed could do to ensure this order: 1. mod_headers 2. mod_pagespeed 3. mod_deflate Should we do something like have a tiny filter function that runs at AP_FTYPE_RESOURCE+1 and queues mod_headers to run and then the real mod_pagespeed filter function but *removes* mod_deflate? Then in the real mod_pagespeed filter function we could queue up mod_deflate to get the ordering we want? Or is that insane /or dangerous? Thanks! -Josh
Re: Inject html into response body
What's your thinking on how you are going to parse the HTML to inject the code? Do you need to parse arbitrary HTML from any website or is this filter targeted at a particular site whose HTML is tailored for this purpose? -Josh On Sun, Dec 4, 2011 at 5:15 PM, r...@tuxteam.de wrote: On Sun, Dec 04, 2011 at 11:47:37PM +0200, O??uzhan TOPG?L wrote: Hi, I' ve search for all the archieve but i couln't find the answer, may be i missed up, don't know. I'm trying to write an apache module and i want to inject some html code into resonses. It might be in body, header or footer. The only thing that i want to implemet is inserting an url or a text into all response bodies without damaging the original page that is serving. Is there any basic way of doing that? Well, why don't you just write an output filter that does this? I think Nick's book will provide all the information you need. Or have a look at mod_include in apache's source code. Cheers, Ralf Mattes thanks Oguzhan
Re: Question about malloc / realloc in module
If you malloc/calloc/realloc without a free you will leak memory. Do you have some reason to believe that another module might prevent your module's calls to free() from being run? What do you have in mind specifically? You can also mimic realloc by just allocating more memory from the pool and calling memcpy. The old memory will leak into the pool but be resolved on pool cleanup. I can tell you that malloc/free works fine inside an Apache module: mod_pagespeed is written in C++ and uses new/delete extensively with the default underlying malloc/free implementation. We load-test extensively and watch for leaks carefully via top, in addition to running valgrind on small system tests. This methodology is sound. I'm not sure why you think your calls to free would not happen. -Josh On Wed, Sep 14, 2011 at 8:01 AM, Christoph Gröver gro...@sitepark.comwrote: Hello list, In a module I have to allocate and reallocate a chunk of memory. Because (AFAIK) Apache or its libraries do not support reallocation I use the standard functions malloc/realloc (and free), of course. But what if there's a problem in another module? Is it possible that due to some errors somewhere else the malloc/realloc of my modules are run (and therefor memory is allocated) but the corresponding free is not called, because the thread/process had a strange ending. So would this result in a memory leak? (if this happens often!) Hope you can enlight me on this topic. Bye, -- Christoph Gröver, gro...@sitepark.com
Re: Apache worker
+modules-dev : someone with a voice of authority should chime in if I (when) say something controversial :) I've not seen any doc on worker MPM vs prefork event. I would love to see that. My observations with Worker MPM is that you will get multiple concurrent requests on the same server_rec, so all access to data you hang off the server_rec should be properly mutex-protected. That was enough -- we believe -- to make our module robust and functional in worker MPM. load-testing is essential, and helped us reproduce prove fixed the two issues we found where we weren't mutexing enough in our module. Also see http://valgrind.org/docs/manual/hg-manual.html. As mentioned in an earlier thread, what was not helpful was the apr pool debug infrastructure, which appears to have insufficient mutexing for its internal debug structures to run correctly in the Worker MPM. I would also love to hear anecdotal evidence of superior performance -- by some metric -- obtained using the Worker MPM. In my own load-test I got higher QPS using prefork, but we haven't tuned our module, which has its own multi-threading architecture independent of MPM, for Worker yet so we probably didn't allocate the optimal number of threads. -Josh On Mon, Sep 12, 2011 at 4:59 AM, Massimo Manghi massimo.man...@unipr.itwrote: Hi Josh I read your messages on the modules-dev list about the problems you had with the worker MPM. Even though you had to deal with some problems with the apr pools it seems you were able to get your module working with a threaded server. I'm the maintainer/developer of Apache Rivet, an Apache module with some extra software for scripting pages using the Tcl language. Our module is working with the prefork mpm, but someone put forward that we should also support 'worker' so I got to work on this. I've been struggling with the worker mpm for a while and had to set it aside because of lack of adequate documentation. What I understand after some debugging is that, from the perspective of a server thread, threads don't simply take the role of prefork processes, there are more implications apart the usual caveats of threaded programming and perhaps there are hooks and specific calls to Apache to deal with threads. Did you take inspiration from some specific threaded module to design your threading support? Did you have some specific reference for this? sorry for the long message. thanks in advance for any suggestion -- Massimo Manghi P.S. I wrote on the list a similar help request weeks ago, but it went totally unanswered
po
Hi, I've been load-testing our module (mod_pagespeedhttp://code.google.com/speed/page-speed/docs/module.html) with httpd 2.2.16 built with these options: --enable-pool-debug --with-mpm=worker I've been getting periodic aborts from apr_table_addn that don't look like they are from my module. These do not occur when using 'prefork'. Here's a stack-trace recovered from a core file: Program terminated with signal 6, Aborted. #0 0x7fdd3bbd9a75 in raise (sig=value optimized out) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64 64 ../nptl/sysdeps/unix/sysv/linux/raise.c: No such file or directory. in ../nptl/sysdeps/unix/sysv/linux/raise.c (gdb) where #0 0x7fdd3bbd9a75 in raise (sig=value optimized out) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64 #1 0x7fdd3bbdd5c0 in abort () at abort.c:92 #2 0x7fdd3c9a2e57 in apr_table_addn (t=0xe84980, key=0xd51d60 Accept-Encoding, val=0xd51d71 identity) at tables/apr_tables.c:813 #3 0x00433e36 in ap_get_mime_headers_core (r=0xf27de0, bb=0xdda3a0) at protocol.c:799 #4 0x0043456b in ap_read_request (conn=0xe51620) at protocol.c:918 #5 0x0047f772 in ap_process_http_connection (c=0xe51620) at http_core.c:183 #6 0x00446e28 in ap_run_process_connection (c=0xe51620) at connection.c:43 #7 0x004b3297 in process_socket (thd=value optimized out, dummy=value optimized out) at worker.c:544 #8 worker_thread (thd=value optimized out, dummy=value optimized out) at worker.c:894 #9 0x7fdd3c1339ca in start_thread (arg=value optimized out) at pthread_create.c:300 #10 0x7fdd3bc8c70d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:112 Questions 1. Is this a bug in httpd? 2. Or could I somehow have caused this with a programming error in my module? 3. Or is enable-pool-debug simply incompatible with the Worker MPM? Thanks, -Josh
Detecting which MPM a module is running in
Hello from mod_pagespeed again. We are adding support for running in the Worker MPM, having spent most of our time since we launched the product sheltered in the prefork MPM where our multi-threading challenges are all of our own making. Having tuned our threading model for prefork, where all request-parallelism will come at the process level, we now offer a functional but, almost certainly, suboptimal experience for Worker MPM users. In particular, for a given server_rec, in prefork we are only going to be processing one request at a time, hence we should employ only a small number of worker threads to help us. But in Worker MPM, from what I've seen, a single server_rec can service multiple concurrent requests. Thus I think we should be aware of this and bump up the number of worker threads we create to help us. Is it possible to detect the MPM under which mod_pagespeed is running, or, more generally, the number of concurrent requests that the current process is likely to need to handle? Thanks! -Josh
Re: po
Hi Ben, Hmmm...don't know what happened to that subject line po. Not what I meant to type, obviously! On Thu, Sep 1, 2011 at 8:14 AM, Ben Noordhuis i...@bnoordhuis.nl wrote: That assertion is triggered when you add a string from pool A to a table in pool B where A is a child of B (adding headers from the request_rec to a conn_rec table, for example). It's a lifecycle issue. OK given the stack-trace above it's hard for me to figure out a path back from my module. Of course a random memory stomp could make any weird thing happen, but only this one specific thing always happens. And we try to avoid memory-stomps via valgrind etc though it's impossible to prove that none exist under load. But I think I've found 2 potential problems in httpd: 1. protocol.c calls apr_table_addn using a char* value that is offset from a pool-allocated string. It's not obvious that it's doing this safely but it makes sense this code has to run crazy fast and has lots of mileage on it. And it's probably OK for the pool-find algorithm appears to do a pointer-range check in apr_pools.c:1908, function pool_find(). For the moment I'll assume this is not the actual problem. 2. there are a bunch of ifdefs in apr_pools.c for POOL_DEBUG and there's a some mutexing for APR_HAS_THREADS, e.g. in apr_allocator_max_free_set. But I suspect the debug structures for POOL_DEBUG are not adequately mutexed. Has anyone specifically used pool-debug and worker-mpm together under heavy load? Thanks! -Josh
Re: Pool Debug Worker MPM compatibility
Oh also I should not that when I do my load-test with pool-debugging off, all is well. The error_log has zero signals/aborts. The main reason I was using pool-debug in the first place was to get better valgrind leak-checks. But if this is just not compatible with Worker MPM I can stay with pool debug off. -Josh On Thu, Sep 1, 2011 at 9:05 AM, Joshua Marantz jmara...@google.com wrote: Hi Ben, Hmmm...don't know what happened to that subject line po. Not what I meant to type, obviously! On Thu, Sep 1, 2011 at 8:14 AM, Ben Noordhuis i...@bnoordhuis.nl wrote: That assertion is triggered when you add a string from pool A to a table in pool B where A is a child of B (adding headers from the request_rec to a conn_rec table, for example). It's a lifecycle issue. OK given the stack-trace above it's hard for me to figure out a path back from my module. Of course a random memory stomp could make any weird thing happen, but only this one specific thing always happens. And we try to avoid memory-stomps via valgrind etc though it's impossible to prove that none exist under load. But I think I've found 2 potential problems in httpd: 1. protocol.c calls apr_table_addn using a char* value that is offset from a pool-allocated string. It's not obvious that it's doing this safely but it makes sense this code has to run crazy fast and has lots of mileage on it. And it's probably OK for the pool-find algorithm appears to do a pointer-range check in apr_pools.c:1908, function pool_find(). For the moment I'll assume this is not the actual problem. 2. there are a bunch of ifdefs in apr_pools.c for POOL_DEBUG and there's a some mutexing for APR_HAS_THREADS, e.g. in apr_allocator_max_free_set. But I suspect the debug structures for POOL_DEBUG are not adequately mutexed. Has anyone specifically used pool-debug and worker-mpm together under heavy load? Thanks! -Josh
Re: po
On Thu, Sep 1, 2011 at 11:16 AM, Ray Morris supp...@bettercgi.com wrote: this code has to run crazy fast and has lots of mileage on it. ... OK given the stack-trace above it's hard for me to figure out a path back from my module. Why not run the test without your new module loaded? This is such an excellent idea. The module is, unfortunately in this case, generating the load for the load-test, as well as handling it. I think I can have the module do *less* but if the module is not loaded at all, then there will be no load. That seems like a far simpler and more reliable indication of whether the issue is in the code with mileage on it or in the new code. The code with mileage in protocol.c is not really under suspicion at this point -- I probably shouldn't have mentioned it, except that it appears in the stack at the time of the abort(), and mod_pagespeed doesn't. The code that I suspect has a lot less mileage on it is the application of pool debugging to the Worker MPM. That's why I want to know if anyone else has put those two together under heavy load. -Josh
Re: Vary:User-Agent, best practices, and making the web faster.
Thanks for the feedback, Ben! You are omniscient in the ways of Apache. I'll try to lobby for an update to the mod_deflate page. Your concerns about Magento are interesting -- my impression from our forums and Twitter is that mod_pagespeed is successfully accelerating many Magento sites now, since releasing the mod_rewrite workarounds, which we were able to do thanks to your help a few months ago. The reason that we don't have problems with vary:user-agent on HTML is that we don't ever cache HTML under any circumstance. We assume HTML generally varies on user-agent, cookies, locale-of-client, and is generally updated frequently. Does Magento actually vary the content of CSS JS based on user-agent? Or does it only vary the content of HTML? You've dissuaded me from trying to infer the intent of the site administrator, and we will find another way to phase in vary:user-agent compliance without falling off a performance cliff. -Josh On Sun, Jun 5, 2011 at 2:54 PM, Ben Noordhuis i...@bnoordhuis.nl wrote: On Sun, Jun 5, 2011 at 13:42, Joshua Marantz jmara...@google.com wrote: This is a case where the content varies based on user-agent. The recommendation on the mod_deflate doc page is add vary:user-agent for any non-image. Can you think of a case where the absence of a vary:user-agent header causes broken behavior when the content doesn't vary? I'm not objecting to setting vary:user-agent when content varies: that's what it's for. I'm objecting to setting vary:user-agent when content does *not* vary. The mod_deflate documentation unambiguously recommends setting vary:user-agent, and my feeling is that this is to work around a bug that exists only in IE5 or pre-2007 patch of IE6. Sorry, Joshua, we're conflating things. You raised two issues in your original post: 1. Updating the mod_deflate documentation. Seems reasonable. The Vary: UA recommendation was added in 2002 during a general clean-up of the mod_deflate documentation and the commit log doesn't tell why. You could open a bugzilla issue or raise it on the httpd-dev mailing list (the former is the proper channel but the bugzilla is something of a graveyard). 2. mod_pagespeed second-guessing the user's intent. That still seems like an unambiguously bad idea. To touch on Magento again, its documentation links (or linked) directly to that section of the mod_deflate docs and people are using that. If your module scans for and neutralizes that Header directive, you will break someone's site.
Vary:User-Agent, best practices, and making the web faster.
Hi, We've been working on a lingering HTTP-compliance issue in mod_pagespeed: respecting Vary:User-Agent. mod_pagespeed needs to cache resources in order to optimize them. The economics of this make sense when the server optimizes a resource, and saves the optimization for serving to multiple clients. The problem is that this is, in general, expensive to do correctly when the site owner has put Vary:User-Agent in the response header for, say, a css or javascript file. There are legitimate reasons to do this, such as serving a different version of a CSS file to IE6. But I think most sites don't do that. However, there is a disturbing passage in the document for mod_deflate: http://httpd.apache.org/docs/2.2/mod/mod_deflate.html: SetEnvIfNoCase Request_URI \ \.(?:gif|jpe?g|png)$ no-gzip dont-vary # Make sure proxies don't deliver the wrong content Header append Vary User-Agent env=!dont-vary This encourages all site owners to add Vary:User-Agent to all css and js files, whether they actually vary in content or not. Does anyone know the history of this recommendation? Surely that is an inappropriate recommendation for mod_deflate. Vary:Accept-Encoding make sense in the context of that filter, but not Vary:User-Agent. The problem with defensively setting Vary:User-Agent is that any proxy cache -- and in this respect mod_pagespeed acts like a proxy cache -- must fetch origin content for each distinct user-agent. While it's feasible for us to employ a level of indirection in our cache so that we only store extra copies of a resource when it actually differs -- this can, I fear, be catestrophic to the cache working-set and hit-rate. We couldn't get around storing each distinct user-agent. So, there are two questions: 1. Who can I lobby to get the recommendation changed for the mod_deflate doc? That recommendation seems incorrect /or obsolete. 2. Given that there are likely a huge number of sites that blindly followed that recommendation, is there a straightforward way for mod_pagespeed to correct the situation? Specifically, can mod_pagespeed get access to apache configuration parameters that were added by other filters, looking specifically for the pattern quoted above with SetEnvIfNoCace Header? Is it OK for mod_pagespeed to register for config-parameters owned by another module? I think what we'd do is basically let mod_pagespeed ignore Vary:User-Agent if we saw that it was inserted per this exact pattern. This would, to be pendantic, violate HTTP, but I think it would help make the web faster, and in practice would help many more sites than it would hurt. Sites that specifically added vary:user-agent using a more specific construct, such as identifying a particular CSS file that they want to Vary, would be treated differently. -Josh
Re: Vary:User-Agent, best practices, and making the web faster.
It was with some reluctance that I brought this up. It occurs to me that this idea propagates the sort of spec violations that led to this issue (inappropriate user of Vary:User-Agent) in the first place. However, I'm trying to figure out how to improve compliance to support legitimate uses of Vary:User-Agent without causing mod_pagespeed to become significantly less ineffective across a broad range of sites. We have found that putting complaints in Apache logs mostly causes disks to fill and servers to crash -- although that does get it noticed :). The problem, put another way, is that mod_pagespeed cannot distinguish legitimate uses of Vary:User-Agent, so it really has no business complaining in logs. Complaining in docs is fine; but some existing mod_pagespeed users that simply type sudo yum update will later notice a performance-drop and may not consult the docs to figure out why. I'm also trying to grok the first response from Eric: It's because of the other (dated) canned exceptions that set/unset no-gzip/gzip-only-text/html based on the User-Agent, to second-guess browsers that send AE:gzip but can't properly deal with it. Going backwards: which browsers send AE:gzip but can't properly deal with it? Does IE6 have that issue or is it only true of IE5? I know that IE6 has had issues with compression in the past but they appear to be addressed by patches issued by Microsoft four and a half years ago: http://support.microsoft.com/default.aspx?scid=kb;en-us;Q312496. Moreover IE6 is shrinking in market sharehttp://arstechnica.com/web/news/2011/05/web-browser-market-share-upgrade-analysis.ars(~ 10%) and IE5 does not appear in the pie-chart at all. And I still don't understand how that relates to Vary:User-Agent. What's really at issue here seems more related to proxies; is that right? That proxies were not respecting Accept-Encoding, but sending gzipped content to browsers that did not want it? Is that still a problem? Which proxies were broken? Are they still broken? And, while I understand the reluctance to help me figure out from our module what values were passed to SetEnvIfNoCase and Header, I would like to see whether there's agreement that the Apache 2.2 docs for mod_deflate are no longer appropriate -- and in fact harmful. -Josh On Sat, Jun 4, 2011 at 5:03 PM, Ben Noordhuis i...@bnoordhuis.nl wrote: On Sat, Jun 4, 2011 at 21:26, Joshua Marantz jmara...@google.com wrote: I think what we'd do is basically let mod_pagespeed ignore Vary:User-Agent if we saw that it was inserted per this exact pattern. This would, to be This seems like a stupendously bad idea. Warn about it in your docs, complain about it in the logs but don't willy-nilly override people's settings.
KeepAlive -- why is it off by default?
webpagetest.org gives a big red *F *to web sites that do* *not have KeepAlive enabled. Yet, at least in the CentOS installation of Apache, it is off by default. Why is that? What are the reasons that KeepAlive should be off? Although it's trivial to turn it on in httpd.conf, many web sites do not do it. We are debating turning it on by default in mod_pagespeed. This seems counterintuitive (and maybe beyond the moral boundaries of our module) but lots of sites on the internet appear to install mod_pagespeed but not bother to turn KeepAlive on. So we could either (a) engage in a campaign to get site owners to understand what KeepAlive is or (b) turn it on by default in mod_pagespeed and perhaps give users an option to stop mod_pagespeed from doing so. What are the reasons someone might wish to turn KeepAlive off? The only one I can think of is in single-process mode (httpd -X) it can be a drag to refresh a page with lots of resources; but this seems like a secondary issue that could be worked around if needed. -Josh
Re: how to parse html content in handler
mod_pagespeed's event-driven HTML parser is open source, and is written in C++: http://code.google.com/p/modpagespeed/source/browse/trunk/src/net/instaweb/htmlparse/public/html_parse.h http://code.google.com/p/modpagespeed/source/browse/trunk/src/net/instaweb/htmlparse/public/html_parse.hThis parser is tested using HTML from large numbers of web sites. The build process for this module ( http://code.google.com/p/modpagespeed/wiki/HowToBuild) generates a separate .a for the HTML parser, although it's got a few dependencies that would need to be linked in. These are all included in mod_pagespeed.so which is self-contained but larger. If there was much interest we could try to try to package up a self-contained library that would make it easier to call from other modules. See also libxml2, which has an HTML mode. -Josh On Fri, Mar 25, 2011 at 9:28 AM, MK m...@cognitivedissonance.ca wrote: On Thu, 24 Mar 2011 20:10:46 +0800 (CST) Whut Jia whut_...@163.com wrote: Hi,all I want to parse a html content and withdraw some element in myself apache handler.Please ask how to do it. Thanks, Jia I think right now the only public C library for parsing html is in the venerable and long unmaintained libwww. However, I wrote a quick and simple, event driven parser library a few months ago -- I have been meaning to open source this on CCAN or somewhere but have not gotten around to it, so if you are interested you can send me a message directly, I have some basic scraper demos etc. It is not on the scale of libwww -- it is just a low level HTML parser -- but I am sure it could do what you want, and you can either compile it in or link to with an apache module (it has no further dependencies). -- Enthusiasm is not the enemy of the intellect. (said of Irving Howe) The angel of history[...]is turned toward the past. (Walter Benjamin)
Re: ordering output filters
Thanks, Nick Ben! On Mon, Mar 14, 2011 at 1:31 PM, Nick Kew n...@apache.org wrote: AP_FTYPE_RESOURCE+1. That also leaves an admin the possibility of overriding it. I didn't realize these +1/-1 hacks were available for this API. This looks really simple is the direction I'm leaning. Why not an insert_filter hook? This is a really good question: I didn't know about this hook. Is there a good place I should go to learn about these hooks myself? Of course, asking this mailing-list has worked really well so far thanks to Ben yourself others. And in particular, adding an insert_filter hook sounds a little more complex than the AP_FTYPE_RESOURCE+1 idea. Is there some advantage to using insert_filter hook? -Josh
Saving the original request URI ahead of a mod_rewrite
Hi, A new bug has surfaced in mod_pagespeed that we understand, but would welcome advice on the best way to fix. The problem is tracked in http://code.google.com/p/modpagespeed/issues/detail?id=234. Briefly, mod_pagespeedhttp://code.google.com/speed/page-speed/docs/using_mod.htmlseeks to improve the performance of web sites by rewriting them while being served from Apache. mod_pagespeed transforms the HTML text in an output filter. To do this correctly, mod_pagespeed needs to know what URL that browser thinks it has when it is displaying a site. The failure scenario is when a site has a RewriteRule in an .htaaccess file. The request-unparsed_uri gets rewritten by mod_rewrite, so by the time mod_pagespeed runs it has the wrong idea of where the page is. This makes mod_pagespeed resolve relative URLs embedded in the HTML in a manner inconsistent from the browser. We thought we had a solution to this problem by putting in an early-running hook that saves the original request-unparsed_uri in request-notes. That seems to work in some cases, but, we've found, not when the RewriteRule is in an .htaccess file. In that case, mod_rewrite triggers an internal redirect, which causes an entirely new 'request' to be allocated, which does *not* have a copy of the original request-notes. It does make a hacked version of request-subprocess_env however, prepending REDIRECT_ to each key. It also seems that the new request has a pointer to the original request (which has the note) in request-prev. But this new request, without the notes, is the one that's passed to mod_pagespeed's output filter, with request-unparsed_uri pointing to the rewritten URL, which is not consistent with the browser's URL bar. So I'm writing to this group to get suggestions on the most robust way to fix this. Here are some ideas: 1. Add an early 'create_request' hook and use that to copy the 'notes' that we care about from request-prev. 2. Change from storing notes in request-notes to request-subprocess_env. When we go to do the lookup with our key, we can look up REDIRECT_key if a note with our original key is not found. This strikes me as a brittle hack. 3. Follow the request-prev chain when looking up notes. This strikes me as risky because I have no idea what happens to the -prev chain through all the modules in the Apache eco-system, or how far down the chain I might have to go. So I like #1 best. Any other opinions or ideas? -Josh
Re: Help with apr mutex
For convenience, you can look at these intriguing new facilities in the SVN repo directly without downloading the tarball: http://svn.apache.org/viewvc/httpd/httpd/trunk/include/ap_socache.h?view=log http://svn.apache.org/viewvc/httpd/httpd/trunk/include/ap_socache.h?view=markup http://svn.apache.org/viewvc/httpd/httpd/trunk/include/ap_socache.h?view=markup http://svn.apache.org/viewvc/httpd/httpd/trunk/include/ap_slotmem.h?view=markup http://svn.apache.org/viewvc/httpd/httpd/trunk/include/ap_slotmem.h?view=markup http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/cache/mod_socache_shmcb.c?view=markup http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/cache/mod_socache_shmcb.c?view=markupIs there any design doc or examples on how these can be used to, say, construct a server-wide cache that can be accessed from any of the child processes in (say) prefork mode? Thanks! -Josh On Tue, Mar 1, 2011 at 10:36 AM, Simone Caruso i...@simonecaruso.comwrote: On 28/02/2011 22:48, Ben Noordhuis wrote: On Mon, Feb 28, 2011 at 18:26, Simone Carusoi...@simonecaruso.com wrote: I wrote a simple cache inside my module with apr_shm and apr_rmm Simone, have a look at ap_socache.h and ap_slotmem.h, they're two simple cache facilities that were added in 2.3.0. Might save you some work. :) I read trunk/modules/cache/mod_socache_shmcb.c too, looks very interesting! Surely I will rewrite my module for 2.3 using socache, thank you Ben. -- Simone Caruso p.iva: 03045250838
Help trying to figure out why an output_filter is not called.
One of the improvements mod_pagespeed is supposed to do to sites is extend the cache lifetime of their resources indefinitely by including a content hash in the URL. This is working well for a large number of sites, but I encountered one today where it does not work. To accomplish the cache extension, overriding any wildcarded or directory-based expire settings a site admin has set for their resources, mod_pagespeed inserts two output filters. The first one does the HTML rewriting: ap_register_output_filter( kModPagespeedFilterName, instaweb_out_filter, NULL, AP_FTYPE_RESOURCE); When instaweb_out_filter runs, it makes this transformation: before: script src=foo.js/script after: script src=foo.js.pagespeed.ce.HASH.js/script The rewritten resource, foo.js.pagespeed.ce.HASH.js, is served by a hook: ap_hook_handler(instaweb_handler, NULL, NULL, APR_HOOK_FIRST - 1); Knowing that mod_headers will later override Cache-Control, which we don't want, our hook serves the .js file with our own header: X-Mod-Pagespeed-Repair: max-age=31536000 We a second output filter, to repair it: // We need our repair headers filter to run after mod_headers. The // mod_headers, which is the filter that is used to add the cache settings, is // AP_FTYPE_CONTENT_SET. Using (AP_FTYPE_CONTENT_SET + 2) to make sure that we // run after mod_headers. ap_register_output_filter( InstawebContext::kRepairHeadersFilterName, repair_caching_header, NULL, static_castap_filter_type(AP_FTYPE_CONTENT_SET + 2)); This is added into the filter chain whenever we want to extend cache: apr_table_add(request-headers_out, X-Mod-Pagespeed-Repair, cache_control); ap_add_output_filter(X-Mod-Pagespeed-Repair, NULL, request, request-connection); When working properly, this header is removed from request-headers_out by repair_caching_header(): const char* cache_control = apr_table_get(request-headers_out, X-Mod-Pagespeed-Repair); if (cache_control != NULL) { SetCacheControl(cache_control, request); apr_table_unset(request-headers_out, kRepairCachingHeader); } Where SetCacheControl also makes the Expires header consistent, etc. While this approach is complex, I've never seen it fail until today, on the site http://law.thu.edu.tw/main.php . On that site, the X-Mod-Pagespeed-Repair header is visible (it should have been removed) and the Cache-Control header has the value set from the conf files (public, max-age=600). So on this server, the repair_caching_header filter is not being run, despite having been programatically inserted by our code in the same place where we add X-Mod-Pagespeed-Repair header. What might be going wrong in his server to cause this to fail? Could some other filter be somehow finding our filter and killing it? Or sending the bytes directly to the network before our filter has a chance to run? Thanks! -Josh
Re: Help trying to figure out why an output_filter is not called.
Thanks again for the fast response, Ben! On Wed, Jan 5, 2011 at 8:57 AM, Ben Noordhuis i...@bnoordhuis.nl wrote: On Wed, Jan 5, 2011 at 14:45, Joshua Marantz jmara...@google.com wrote: other filter be somehow finding our filter and killing it? Or sending the bytes directly to the network before our filter has a chance to run? Possibly, yes. Can you elaborate? Is this a common practice, to write bytes directly to the network from an output filter? What should I look for? The owner of the site where this is breaking sent me a few conf files and it enumerates some of the modules inserted: LoadModule perl_module modules/mod_perl.so LoadModule mono_module modules/mod_mono.so LoadModule bwlimited_module modules/mod_bwlimited.so LoadModule bw_module modules/mod_bw.so LoadModule jk_module modules/mod_jk.so Does anyone know anything about these? Could one of these have inserted an output filter that spews bytes directly to the network? I'll try to find sources for those but if someone knows off-hand that would be helpful. By the way, why the complex setup? If you don't want the mod_headers filter to run, insert your filter before it, then remove it for each request that you handle. This is an interesting idea. I guess we should eliminate FIXUP_HEADERS_OUT, FIXUP_HEADERS_ERR, and MOD_EXPIRES. Are there any other similar header-mucking-filters I need to kill? I don't mind squirreling through the source code to find these names (all are string literals in .c files) but I'm nervous they could change without warning in a future version. Moreover, expires_insert_filter runs as APR_HOOK_MIDDLE which means it runs after my content-generator, which means that it won't have been inserted by the time when I want to set my caching headers. I guess that means I have to insert a new late-running hook that kills undesirable output filters. Does that wind up being simpler? -Josh
Re: Help trying to figure out why an output_filter is not called.
On Wed, Jan 5, 2011 at 10:43 AM, Ben Noordhuis i...@bnoordhuis.nl wrote: I guess we should eliminate FIXUP_HEADERS_OUT, FIXUP_HEADERS_ERR, and MOD_EXPIRES. Are there any other similar header-mucking-filters I need to kill? Moreover, expires_insert_filter runs as APR_HOOK_MIDDLE which means it runs after my content-generator, which means that it won't have been inserted by the time when I want to set my caching headers. You can remove it from your handler, scan r-output_filters-frec-name to find the filter. I'm not following you. mod_expires.c has this: static void expires_insert_filter(request_rec *r) { ...ap_add_output_filter(MOD_EXPIRES, NULL, r, r-connection);... } static void register_hooks(apr_pool_t *p) { /* mod_expires needs to run *before* the cache save filter which is * AP_FTYPE_CONTENT_SET-1. Otherwise, our expires won't be honored. */ ap_register_output_filter(MOD_EXPIRES, expires_filter, NULL, AP_FTYPE_CONTENT_SET-2); ap_hook_insert_error_filter(expires_insert_filter, NULL, NULL, APR_HOOK_MIDDLE); ap_hook_insert_filter(expires_insert_filter, NULL, NULL, APR_HOOK_MIDDLE); } So if I try to remove the 'expires' filter from my handler (which runs early) then mod_expires will have a handler that runs later that inserts it after my module has completed. Hence: I guess that means I have to insert a new late-running hook that kills undesirable output filters. Does that wind up being simpler? The above is probably easier but whatever ends up being the most readable / maintainable, right? And also functional :) which, evidently, my current solution is not, at least in the presence of mod_perl and mod_php. Your solution has the advantage of being more robust when upstream filters write directly to the network. I just wish I didn't have to depend on my copies of string literals from .c files I don't control. But as you said core-filters will hopefully not change internal string constants often. I just coded it up and it seems to work :) -Josh
Re: Help trying to figure out why an output_filter is not called.
This has certainly gotten off topic :) http://www.google.com/search?sourceid=chromeie=UTF-8q=nginx+vs+apache has lots of interesting opinions on the subject. Having said that, mod_pagespeed's initial target is Apache because that's the dominant server stack driving the web. I'm optimistic that nginx will also be a compelling opportunity at some point and I'm anxious to learn more. Now -- back on topic -- this issue is tracked as http://code.google.com/p/modpagespeed/issues/detail?id=179 for those following along at home, and hopefully will be resolved shortly based on the advise of the contributors to this thread. Thanks again, everyone, -Josh On Wed, Jan 5, 2011 at 8:40 PM, Ray Morris supp...@bettercgi.com wrote: Just a quick note since you mentioned nginx. Nginx is of course normally used by people wanting higher performance than they are getting from Apache, because certain tests seemed to suggest that nginx can significantly outperform Apache in some cases. If that's the case for you, we learned something very interesting. We wondered how nginx could possibly be much faster since the speed of the disk itself is normally the limiting factor. Was there something to be learned from nginx which could be applied to Apache? At the end of all of the testing, we learned what caused the large apparent difference. noatime. Nginx effectively skips atime updates, which can make a huge difference. By simply mounting the directory with the noatime option, any reasonable Apache configuration will have about the same performance as nginx, which is basically the performance of the underlying storage. People build complex systems with nginx as a proxy to Apache, but the same or better performance, with better standards compliance and better reliability, can be obtained by just setting noatime directly rather than using getting noatime accidentally as a side effect of nginx. With noatime set, one server or another might be 1% faster, but using TWO servers, with one as a proxy, will be slower than just simply using Apache, and in no case will nginx be SIGNIFICANTLY faster, when using noatime. -- Ray Morris supp...@bettercgi.com Strongbox - The next generation in site security: http://www.bettercgi.com/strongbox/ Throttlebox - Intelligent Bandwidth Control http://www.bettercgi.com/throttlebox/ Strongbox / Throttlebox affiliate program: http://www.bettercgi.com/affiliates/user/register.php On 01/05/2011 03:16:21 PM, Ben Noordhuis wrote: On Wed, Jan 5, 2011 at 22:03, Joshua Marantz jmara...@google.com wrote: Right you are. That's much simpler then. Thanks! My pleasure, Joshua. Two quick questions, hope you don't mind: Is mod_pagespeed an official Google project? Or is it something you guys do on your day off? And are there plans for a nginx port?
Re: Help trying to figure out why an output_filter is not called.
This is my day job at google. We would love to do an nginx port but have not scheduled it yet. sent from my android On Jan 5, 2011 4:16 PM, Ben Noordhuis i...@bnoordhuis.nl wrote: On Wed, Jan 5, 2011 at 22:03, Joshua Marantz jmara...@google.com wrote: Right you are. That's much simpler then. Thanks! My pleasure, Joshua. Two quick questions, hope you don't mind: Is mod_pagespeed an official Google project? Or is it something you guys do on your day off? And are there plans for a nginx port?
Re: Overriding mod_rewrite from another module
OK I tried to find a more robust alternative but could not. I was thinking I could duplicate whatever mod_rewrite was doing to set the request filename that appears to be complex and probably no less brittle. I have another query on this. In reality we do *not* want our rewritten resources to be associated with a filename at all. Apache should never look for such things in the file system under ../htdocs -- they will not be there. We also do not need it to validate or authenticate on these static resources. In particular, we have found that there is some path through Apache that imposes what looks like a file-system-based limitation on URL segments (e.g. around 256 bytes). This limitation is inconvenient and, as far as I can tell, superfluous. URL limits imposed by proxies and browsers are more like 2k bytes, which would allow us to encode more metadata in URLs (e.g. sprites). Is there some magic setting we could put into the request structure to tell Apache not to interpret the request as being mapped from a file, but just to pass it through to our handler? Thanks! -Josh On Sat, Jan 1, 2011 at 6:24 AM, Ben Noordhuis i...@bnoordhuis.nl wrote: On Sat, Jan 1, 2011 at 00:16, Joshua Marantz jmara...@google.com wrote: Thanks for the quick response and the promising idea for a hack. Looking at mod_rewrite.c this does indeed look a lot more surgical, if, perhaps, fragile, as mod_rewrite.c doesn't expose that string-constant in any formal interface (even as a #define in a .h). Nevertheless the solution is easy-to-implement and easy-to-test, so...thanks! You're welcome, Joshua. :) You could try persuading a core committer to add this as a (semi-)official extension. Nick Kew reads this list, Paul Querna often idles in #node.js at freenode.net. I'm also still wondering if there's a good source of official documentation for the detailed semantics of interfaces like ap_hook_translate_name. Neither a Google Search, a stackoverflow.com search, nor the Apache Modules http://www.amazon.com/Apache-Modules-Book-Application-Development/dp/0132409674/ref=sr_1_1?ie=UTF8qid=1293837117sr=8-1 book offer much detail. code.google.com fares a little better but just points to 4 existing usages. This question comes up often. In my experience the online documentation is almost always outdated, incomplete or outright wrong. I don't bother looking things up, I go straight to the source. It's a kind of job security, I suppose. There are only a handful of people that truly and deeply understand Apache. We can ask any hourly rate we want!
Re: Overriding mod_rewrite from another module
I have implemented Ben's hack in mod_pagespeed in http://code.google.com/p/modpagespeed/source/detail?r=345 . It works great. But I am concerned that a subtle change to mod_rewrite.c will break this hack silently. We would catch it in our regression tests, but the large number of Apache users that have downloaded mod_pagespeed do not generally run our regression tests. I have another idea for a solution that I'd like to see opinions on. Looking at Nick Kew's book, it seems like I could set request-filename to whatever I wanted, return OK, but then also shunt off access_checker for my rewritten resources. The access checking on mod_pagespeed resources is redundant, because the resource will either be served from cache (in which case it had to be authenticated to get into the cache in the first place) or will be decoded and the original resource(s) fetched from the same server with full authentication. I'd appreciate any comments on this approach. -Josh On Mon, Jan 3, 2011 at 11:40 AM, Joshua Marantz jmara...@google.com wrote: OK I tried to find a more robust alternative but could not. I was thinking I could duplicate whatever mod_rewrite was doing to set the request filename that appears to be complex and probably no less brittle. I have another query on this. In reality we do *not* want our rewritten resources to be associated with a filename at all. Apache should never look for such things in the file system under ../htdocs -- they will not be there. We also do not need it to validate or authenticate on these static resources. In particular, we have found that there is some path through Apache that imposes what looks like a file-system-based limitation on URL segments (e.g. around 256 bytes). This limitation is inconvenient and, as far as I can tell, superfluous. URL limits imposed by proxies and browsers are more like 2k bytes, which would allow us to encode more metadata in URLs (e.g. sprites). Is there some magic setting we could put into the request structure to tell Apache not to interpret the request as being mapped from a file, but just to pass it through to our handler? Thanks! -Josh On Sat, Jan 1, 2011 at 6:24 AM, Ben Noordhuis i...@bnoordhuis.nl wrote: On Sat, Jan 1, 2011 at 00:16, Joshua Marantz jmara...@google.com wrote: Thanks for the quick response and the promising idea for a hack. Looking at mod_rewrite.c this does indeed look a lot more surgical, if, perhaps, fragile, as mod_rewrite.c doesn't expose that string-constant in any formal interface (even as a #define in a .h). Nevertheless the solution is easy-to-implement and easy-to-test, so...thanks! You're welcome, Joshua. :) You could try persuading a core committer to add this as a (semi-)official extension. Nick Kew reads this list, Paul Querna often idles in #node.js at freenode.net. I'm also still wondering if there's a good source of official documentation for the detailed semantics of interfaces like ap_hook_translate_name. Neither a Google Search, a stackoverflow.com search, nor the Apache Modules http://www.amazon.com/Apache-Modules-Book-Application-Development/dp/0132409674/ref=sr_1_1?ie=UTF8qid=1293837117sr=8-1 book offer much detail. code.google.com fares a little better but just points to 4 existing usages. This question comes up often. In my experience the online documentation is almost always outdated, incomplete or outright wrong. I don't bother looking things up, I go straight to the source. It's a kind of job security, I suppose. There are only a handful of people that truly and deeply understand Apache. We can ask any hourly rate we want!
Re: Overriding mod_rewrite from another module
On Mon, Jan 3, 2011 at 4:50 PM, Ben Noordhuis i...@bnoordhuis.nl wrote: This means that returning OK from my handler does not prevent mod_authz_host's handler from being called. You're mistaken, Joshua. The access_checker hook by default is empty. mod_authz_host is a module and it can be disabled (if you're on a Debian/Ubuntu system, run `a2dismod authz_host` and reload Apache). My perspective is that my team has implemented an Apache module that was launched on Nov 3 2010. Since its launch, we've encountered a variety of compatibility reports with other modules, notably mod_rewrite. My goal is not to remove authentication from the server; only from messing with my module's rewritten resource. The above statement is just observing that, while it's possible to shunt off mod_rewrite by returning OK from an upstream handler, the same is not true of mod_authz_host because it's invoked with a different magic macro. With respect to the URL length, I'm fairly sure it's nearly 8K (grep for HUGE_STRING_LEN in core_filters.c). There may exist some buffer in Apache that's 8k. But I have traced through failing requests earlier that were more like 256 bytes. This was reported as mod_pagespeed Issue 9http://code.google.com/p/modpagespeed/issues/detail?id=9 and resolved by limiting the number of css files that could be combined together so that we did not exceed the pathname limitations. I'm pretty sure it was due to some built-in filter or core element in httpd trying to map the URL to a filename (which is not necessary as far as mod_pagespeed is concerned) and bumping into an OS path limitation (showing up as 403 Forbidden). I confess I'm not entirely sure what you are trying to accomplish. You're serving up custom content and you're afraid mod_rewrite is going to munch the URL? Or is it more involved than that? That's exactly right. The simplest example is mod_pagespeed can infinitely extend the cache lifetime of a js file, without compromising the site owner's ability to propagate changes quickly, by putting an md5-hash of the css content into the URL. old: script src=scripts/hacks.js/script new: script src=scripts/hacks.js*.pagespeed.ce.HASH.js*/script If some mod_rewrite rule munges scripts/hacks.js.ce.pagespeed.HASH.js, then mod_pagespeed will fail to serve it. The issue is most simply stated in a Stack Overflow article: http://stackoverflow.com/questions/4099659/mod-rewrite-mod-pagespeed-rewritecond In this case, the user had hand-entered a mod_rewrite rule that broke mod_pagespeed so it made sense for him to fix it there. However, we have heard reports of other cases where a user installs some content-generation software that generate mod_rewrite rules that break mod_pagespeed. Such users may not even know what mod_rewrite is, so they can't easily work around the broken rules. This issue is reported as mod_pagespeed Issue 63http://code.google.com/p/modpagespeed/issues/detail?id=63 . Hope this clears things up. I'm still interested in your opinion on my solution where I (inspired by your hack) save the original URL in request-notes and then use *that* in my resource handler in lieu of request-unparsed_uri. This change is now committed to svn trunk (but not released in a formal patch) as http://code.google.com/p/modpagespeed/source/detail?r=348 . -Josh
Re: Overriding mod_rewrite from another module
On Mon, Jan 3, 2011 at 6:15 PM, Eric Covener cove...@gmail.com wrote: The access checking on mod_pagespeed resources is redundant, because the resource will either be served from cache (in which case it had to be authenticated to get into the cache in the first place) or will be decoded and the original resource(s) fetched from the same server with full authentication. Re: suppressing mod_authz_host: This doesn't sound like it guards against a user that meets the AAA conditions causing the resource to be cached and served to users who would not have met the AAA restrictions. This is a good point, but I think I'm covered. mod_pagespeed will only rewrite resources that are publicly cacheable. What does AAA stand for? Authorization Authentication in Apache or something? In any case I've abandoned, for the moment, the attempt to bypass mod_authz_host on a per-request basis. Maybe you are missing a map_to_storage callback to tell the core that this thing will really, really not be served from the filesystem. I was not aware of the concept of a map_to_storage callback at all. I will have to investigate. This may be very helpful. Thanks. Re: suppressing rewrite. Your comments in the src imply that rewrite is doing some of what you're also suppressing in server/core.c:ap_core_translate_name(). Also, it's odd that your scheme for suppressing mod_rewrite wasn't a no-op for rewrite in htaccess context, since these use the RUN_ALL fixups hook to do its magic, but maybe you're catching a break there? It's quite possible that the previous hack where we use the node mod_rewrite_rewritten would break if mod_rewrite.c:hook_uri2file's functional component could get called by mod_rewrite.c:hook_fixup, but I haven't analyzed the module deeply enough to understand it at that level. But I think the present hack, where we don't turn off mod_rewrite but just ignore its output via our own request-note will be more robust. At least I hope it will. In my testing 2 weeks ago I had trouble invoking mod_rewrite from .htaccess. I'll have to try again. -Josh
Re: Overriding mod_rewrite from another module
I answered my own question by implementing it and failing. You can't bypass mod_authz_host because it gets invoked via the magic macro: AP_IMPLEMENT_HOOK_RUN_ALL(int,access_checker, (request_rec *r), (r), OK, DECLINED) This means that returning OK from my handler does not prevent mod_authz_host's handler from being called. I came up with a simpler idea that does not require depending on string-literals in mod_rewrite.c. I still add a translate_name hook to run prior to mod_rewrite, but I don't try to prevent mod_rewrite from corrupting my URL. Instead I just squirrel away the uncorrupted URL in my own entry in request-notes so that I can use that rather than request-unparsed_uri downstream when processing the request. This seems to work well. The only drawback is if the site admin adds a mod_rewrite rule that mutates mod_pagespeed's resource name into something that does not pass authentication, then mod_authz_host will reject the request before I can process it. This seems like a reasonable tradeoff as that configuration would likely be borked in other ways besides mod_pagespeed resources. Commentary would be welcome. -Josh On Mon, Jan 3, 2011 at 1:10 PM, Joshua Marantz jmara...@google.com wrote: I have implemented Ben's hack in mod_pagespeed in http://code.google.com/p/modpagespeed/source/detail?r=345 . It works great. But I am concerned that a subtle change to mod_rewrite.c will break this hack silently. We would catch it in our regression tests, but the large number of Apache users that have downloaded mod_pagespeed do not generally run our regression tests. I have another idea for a solution that I'd like to see opinions on. Looking at Nick Kew's book, it seems like I could set request-filename to whatever I wanted, return OK, but then also shunt off access_checker for my rewritten resources. The access checking on mod_pagespeed resources is redundant, because the resource will either be served from cache (in which case it had to be authenticated to get into the cache in the first place) or will be decoded and the original resource(s) fetched from the same server with full authentication. I'd appreciate any comments on this approach. -Josh On Mon, Jan 3, 2011 at 11:40 AM, Joshua Marantz jmara...@google.comwrote: OK I tried to find a more robust alternative but could not. I was thinking I could duplicate whatever mod_rewrite was doing to set the request filename that appears to be complex and probably no less brittle. I have another query on this. In reality we do *not* want our rewritten resources to be associated with a filename at all. Apache should never look for such things in the file system under ../htdocs -- they will not be there. We also do not need it to validate or authenticate on these static resources. In particular, we have found that there is some path through Apache that imposes what looks like a file-system-based limitation on URL segments (e.g. around 256 bytes). This limitation is inconvenient and, as far as I can tell, superfluous. URL limits imposed by proxies and browsers are more like 2k bytes, which would allow us to encode more metadata in URLs (e.g. sprites). Is there some magic setting we could put into the request structure to tell Apache not to interpret the request as being mapped from a file, but just to pass it through to our handler? Thanks! -Josh On Sat, Jan 1, 2011 at 6:24 AM, Ben Noordhuis i...@bnoordhuis.nl wrote: On Sat, Jan 1, 2011 at 00:16, Joshua Marantz jmara...@google.com wrote: Thanks for the quick response and the promising idea for a hack. Looking at mod_rewrite.c this does indeed look a lot more surgical, if, perhaps, fragile, as mod_rewrite.c doesn't expose that string-constant in any formal interface (even as a #define in a .h). Nevertheless the solution is easy-to-implement and easy-to-test, so...thanks! You're welcome, Joshua. :) You could try persuading a core committer to add this as a (semi-)official extension. Nick Kew reads this list, Paul Querna often idles in #node.js at freenode.net. I'm also still wondering if there's a good source of official documentation for the detailed semantics of interfaces like ap_hook_translate_name. Neither a Google Search, a stackoverflow.com search, nor the Apache Modules http://www.amazon.com/Apache-Modules-Book-Application-Development/dp/0132409674/ref=sr_1_1?ie=UTF8qid=1293837117sr=8-1 book offer much detail. code.google.com fares a little better but just points to 4 existing usages. This question comes up often. In my experience the online documentation is almost always outdated, incomplete or outright wrong. I don't bother looking things up, I go straight to the source. It's a kind of job security, I suppose. There are only a handful of people that truly and deeply understand Apache. We can ask any hourly rate we want!
Overriding mod_rewrite from another module
I need to find the best way to prevent mod_rewrite from renaming resources that are generated by a different module, specifically mod_pagespeed. This needs to be done from within mod_pagespeed, rather than asking the site admin to tweak his rule set. By reading mod_rewrite.c, I found a mechanism that appears to work. But it has its own issues and I'm having trouble finding any relevant doc about the mechanism: ap_hook_translate_name(bypass_translators, APR_HOOK_FIRST -1); bypass_translators returns OK for resources generated by the module, preventing mod_rewrite from disturbing them. It returns DECLINED for other resources. The trouble is that httpd seems to report error messages in the log for the lack of a filename. We can set the request-filename to something but that causes the requests to fail completely on some servers. We haven't isolated the difference between servers that can handle the fake filename and ones that can't yet. Is there a better way to solve the original problem: preventing mod_rewrite from corrupting mod_pagespeed's resources? Or is there better doc on the semantics of the request.filename field in the context of a resource that is not stored as a file? Or on ap_hook_translate_name? sent from my android
Re: Overriding mod_rewrite from another module
Thanks for the quick response and the promising idea for a hack. Looking at mod_rewrite.c this does indeed look a lot more surgical, if, perhaps, fragile, as mod_rewrite.c doesn't expose that string-constant in any formal interface (even as a #define in a .h). Nevertheless the solution is easy-to-implement and easy-to-test, so...thanks! I'm also still wondering if there's a good source of official documentation for the detailed semantics of interfaces like ap_hook_translate_name. Neither a Google Search, a stackoverflow.com search, nor the Apache Moduleshttp://www.amazon.com/Apache-Modules-Book-Application-Development/dp/0132409674/ref=sr_1_1?ie=UTF8qid=1293837117sr=8-1book offer much detail. code.google.com fares a little better but just points to 4 existing usages. -Josh On Fri, Dec 31, 2010 at 1:50 PM, Ben Noordhuis i...@bnoordhuis.nl wrote: On Fri, Dec 31, 2010 at 18:17, Joshua Marantz jmara...@google.com wrote: Is there a better way to solve the original problem: preventing mod_rewrite from corrupting mod_pagespeed's resources? From memory and from a quick peek at mod_rewrite.c: in your translate_name hook, set a mod_rewrite_rewritten note in r-notes with value 0 and return DECLINED. That'll trick mod_rewrite into thinking that it has already processed the request.
Re: Howto unittest httpd modules?
For mod_pagespeed http://code.google.com/speed/page-speed/docs/module.htmlwe do 2 of the 3 testing modes discussed. We have the majority of our code running independent of Apache so it can be aggressively unit-tested with googletesthttp://code.google.com/p/googletest/ . We also have automated system-tests with our module running inside of Apache. They are pretty painless once it is set up. We use 'wget' for control and observation. This doesn't have nearly the functional coverage of the unit tests but does check that stuff is hooked up and working in the system: http://code.google.com/p/modpagespeed/source/browse/trunk/src/install/system_test.sh http://code.google.com/p/modpagespeed/source/browse/trunk/src/install/system_test.shWe also have stress tests that work in a similar way. http://code.google.com/p/modpagespeed/source/browse/trunk/src/install/stress_test.sh Our development flow integrates the system-test into the pre-submit checks; it really doesn't take very much time at all. It does require that every developer has a debug instance of Apache into which they can automatically copy modules and restart servers. We have talked about writing a 'fakehttp://en.wikipedia.org/wiki/Mock_object' Apache so that we could properly unit-test all of our code. But given the speed of automated system testing, it seems unlikely we'd focus on this anytime soon. Hope this helps, -Josh On Mon, Nov 22, 2010 at 5:05 AM, Edgar Frank ef-li...@email.de wrote: 2010/11/11 Sorin Manolache: On Thu, Nov 11, 2010 at 08:11, Edgar Frank ef-li...@email.de wrote: I've written a handful of modules for httpd. I'm now looking for a way to setup some unit tests. We have continuous integration running, so I want to supply some tests, starting from compiling against httpd to basic functionality to more elaborate feature tests. I wonder how to unit-test this, as the prerequsites are rather complicated. The tests would have to setup a httpd, provide a config, compile and install the modules. As you don't want to modify the modules themselves, you have to run a bunch of requests and monitor expected output - maybe measuring coverage or running valgrind on the way. I see no way to run real unit tests as you would have to emulate httpd and run your modules against it, as most of the code is httpd or at least highly APR dependent. I see no point in emulating httpd as you would have to implement every little detail - httpd specific behaviour (e.g. in version bumps) is one important thing to test IMHO. So, has anyone some experience with this, some suggestions, howtos or tutorials? Any help would be greatly appreciated. In our group we unit test only parts of our modules. We unit test the callbacks and their sequence (a sort of poor-man's emulation of httpd). We populate a request_rec structure and then we pass it to the various callbacks. Our callbacks are mainly wrappers around bigger functions that are httpd-independent. The apache filters are tested in this way. The part that needed more code in order to emulate httpd was the subrequest infrastructure. Thanks for your reply. Unfortunately this is the way we're trying to avoid if possible. Has anyone else some hints or best pratices, besides emulating httpd? Is there even another way? Regards, Edgar