From 99d6a20600b94646bf75c0baf545cd914be51389 Mon Sep 17 00:00:00 2001 From: Lucian Mogosanu Date: Fri, 16 Aug 2019 19:46:46 +0300 Subject: [PATCH] posts: 09b --- drafts/000-hunchentoot-v.markdown | 258 ----------------------------- posts/y06/09b-hunchentoot-v.markdown | 298 ++++++++++++++++++++++++++++++++++ 2 files changed, 298 insertions(+), 258 deletions(-) delete mode 100644 drafts/000-hunchentoot-v.markdown create mode 100644 posts/y06/09b-hunchentoot-v.markdown diff --git a/drafts/000-hunchentoot-v.markdown b/drafts/000-hunchentoot-v.markdown deleted file mode 100644 index 9b84bcc..0000000 --- a/drafts/000-hunchentoot-v.markdown +++ /dev/null @@ -1,258 +0,0 @@ ---- -postid: 000 -title: Hunchentoot: taskmaster code review -date: August 16, 2019 -author: Lucian Mogoșanu -tags: tech, tmsr ---- - -Hunchentoot taskmasters are, as the name suggests, an abstraction for -work management, or in other words, they implement decision-making for -work distribution among processing units. On the surface they look -very similar to Apache's [MPM][apache-mpm] model, which (again, viewed -very superficially) suggests Hunchentoot was lispers' attempt at an -Apache reimplementation. - -As presented in the earlier [architectural overview][ht-iii], -taskmasters expose the following methods: execute-acceptor, -handle-incoming-connection and shutdown. In very broad lines, -execute-acceptor gets called on [start][ht-s] and sets up an execution -context where [accept-connections][ht-ac] is called; -handle-incoming-connection is then called on each new connection and -calls [process-connection][ht-pc]; and finally, shutdown is called by -[stop][ht-pc], to suspend processing on all threads. Additionally, -(specific) taskmasters may expose other methods[^1] that specific to -their operation. - -The taskmaster class provides three subclasses: a single-threaded -implementation, an abstract "multi-threaded" taskmaster and a concrete -"one thread per connection" taskmaster -- otherwise the coad under -examination is also structured to accommodate the usual -[ifdefisms][ht-ifdefism], which we'll blissfully ignore. This being -said, let us look at each taskmaster and the method it implements. - -[s3] [**shutdown**][ht-s3]: This is a -generic implementation, that can be (and is, in one case, as shown -below) overriden by subclasses; this implementation doesn't do -anything except returning the taskmaster object. - -[**single-threaded-taskmaster**][ht-stt]: The simplest taskmaster -implementation; probably not very useful for battlefield use, because -of poor load handling, [blocking operations][tlogz-1926874] and so on. - -[stt-ea] -[**execute-acceptor**][ht-stt-ea]: Calls [accept-connections][ht-ac]. - -[stt-hic] -[**handle-incoming-connection**][ht-stt-hic]: Calls -[process-connection][ht-pc]. - -Shutdown is provided by the [generic implementation](#s3) above. - -[**multi-threaded-taskmaster**][ht-mtt]: Defines a new -[acceptor-process][ht-mtt-ap] field denoting a new thread whose sole -work is accepting new connections. Thus, this acceptor only provides -an implementation for: - -[mtt-ea] -[**execute-acceptor**][ht-mtt-ea]: Starts a new "listener" thread -which waits for new connections; essentially the same as [the -single-threaded version](#ht-stt-ea), only accept-connections runs on -a separate thread. - -All the other methods are implemented by -sub-multi-threaded-taskmasters, i.e. by -one-thread-per-connection-taskmaster[^2]. - -[**one-thread-per-connection-taskmaster**][ht-otpct]: As the name -suggests, each new connection will spawn a new thread when it is to be -handled. Up to [max-thread-count][ht-otpct-mtc] connections are -accepted, and then the remaining connections up to -[max-accept-count][ht-otpct-mac] are [queued][ht-otpct-wq] waiting for -a thread to be allocated for them. If both counts are exceeded (or if -the former is exceeded and the latter is not set) then a HTTP 503 is -sent to the client. - -Below I'll detail (top-down) the implementation of -handle-incoming-connection, shutdown and (the additional) -initialize-instance -- the execute-acceptor used is that of the -[superclass](#mtt-ea). - -[otpct-ii] -[**initialize-instance**][ht-otpct-ii]: This is an ":after" method -which, given a new taskmaster instance, does some sanity checking, -i.e. that: a. if max-accept-count is supplied, then so is -max-thread-count, and b. that the former is higher than the -latter. The idea here is that the number of Hunchentoot worker threads -is either unlimited, or limited by max-thread-count -- in the former -case, max-accept-count doesn't really make sense, because all new -connections are accepted. - -[otpct-hic] -[**handle-incoming-connection**][ht-otpct-hic]: Calls -[create-request-handler-thread](#otpct-crht); in other words, it -creates a new thread to handle requests associated with the current -connection. - -[otpct-s3] -[**shutdown**][ht-otpct-s3]: Joins (in the Unix sense of "thread -join") the acceptor-process, i.e. the [listener](#mtt-ea) thread and -returns the current taskmaster. - -As observed, these methods are implemented using the following -"support" methods and functions: - -[otpct-itac] -[**increment-taskmaster-accept-count**][ht-otpct-itac]: Atomically -increments the accept-count at a given time. - -[otpct-dtac] -[**decrement-taskmaster-accept-count**][ht-otpct-dtac]: Atomically -decrements the accept-count at a given time. - -[otpct-ittc] -[**increment-taskmaster-thread-count**][ht-otpct-ittc]: Atomically -increments the thread-count at a given time. - -[otpct-dttc] -[**decrement-taskmaster-thread-count**][ht-otpct-dttc]: Atomically -decrements the thread-count at a given time; when thread-count falls -under max-accept-count, notifies listener via -[note-free-connection](#otpct-nfc) that new connections may be -handled. - -[otpct-nfc] -[**note-free-connection**][ht-otpct-nfc]: [Signals][ht-cvs] the -taskmaster's wait-queue; as the name suggests, it's used when there -are "free" "slots" available for connections to be handled. - -[otpct-wffc] -[**wait-for-free-connection**][ht-otpct-wffc]: [Waits][ht-cvw] for -"free" connection "slots" on the taskmaster's wait-queue; used when -there aren't (yet) enough resources to process a given connection. - -[otpct-tmtr] -[**too-many-taskmaster-requests**][ht-otpct-tmtr]: Calls -[acceptor-log-message][ht-alm]; logs the situation when the -taskmaster's wait-queue is full or, if max-accept-count isn't set, -that the thread-count has reached the ceiling i.e. max-thread-count. - -[otpct-crht] -[**create-request-handler-thread**][ht-otpct-crht]: a. Wrapped in a -[handler-case\*][ht-hcs]; b. start a new thread; c. which calls -[handle-incoming-connection%](#otpct-hic2). In case of errors, -d1. close the current connection's socket stream, aborting the -connection; and d2. log the error. - -[otpct-hic2] -[**handle-incoming-connection%**][ht-otpct-hic]: The description -contained in the function's definition is pretty good, but -nevertheless, let's look at this in more detail: -a. [increment-taskmaster-accept-count](#otpct-itac); b. create a local -binding for process-connection%, which b1. calls -[process-connection][ht-pc] b2. with the [thread-count -incremented](#otpct-ittc); c. implement the logic described below. - -c1. if thread-count is null, then [process-connection][ht-pc]; -otherwise, c2. *if* either max-accept-count is set and accept-count is -at this threshold, *or* max-accept-count isn't set and thread-count is -at the max-thread-count threshold, *then* call -[too-many-taskmaster-requests](#otpct-tmtr) and -[send-service-unavailable-reply](#otpct-ssur), which ends the current -connection; otherwise, c3. *if* max-accept-count is set *and* -thread-count is larger than max-thread-count *then* -[wait-for-free-connection](#otpct-wffc), then, when unblocked, -process-connection%; otherwise, c4. process-connection%. - -As can be observed, handle-incoming-connection% implements the bulk of -the decision-making process for one-thread-per-connection -taskmasters. This isn't *very* difficult to wrap one's head around, -despite the apparent gnarl; simplifications, at the very least of an -aesthetic nature, are possible, I'll leave them as a potential -exploration exercise for a later date -- or, if the reader desires to -chime in... - -[otpct-ssur] -[**send-service-unavailable-reply**][ht-otpct-ssur]: Yet another pile -of gnarl. Wraps everything in an [unwind-protect][clhs-up] and catches -all potential conditions. In this context, it sends a -http-service-unavailable message with the content set to the text -returned by [acceptor-status-message][ht-asm]. - -At the end, [decrement-taskmaster-accept-count](#otpct-dtac) and flush -and close the connection stream. - -[otpct-cas] -[**client-as-string**][ht-otpct-cas]: Convenience function used by -[create-request-handler-thread](#otpct-crht) to give a name to the -thread to be created, of the form "address:port". - -As can be seen, this is still a monster, albeit more organized than -its [acceptor][ht-iv] brother. At this point, the big remaining pieces -are requests, replies and handler dispatchers, which should provide us -with almost[^3] everything we need to actually have a Hunchentoot. - -[^1]: Though all methods are piled together in the same place and, - say, default "thread count" implementations are provided for some - taskmasters that have nothing to do with multithreading. This is - a first sign that whoever wrote the code must have been fucked - in the head. - -[^2]: Which isn't to say there couldn't be more than one - multi-threaded-taskmaster implementation, we just haven't seen any - others. The very same, however, could be said about - e.g. shit. Sure, it could come from a human, a cow or a horse, but - for all intents and purposes it's still shit, so why the - additional layer of indirection? - - Oh, it could be extended? Well, show me one of these - extensions. And if there are any, why aren't they in Hunchentoot? - -[^3]: There's tons of [glue][tmsr-work-iv] poured around this set of - fundamentally TCPistic web-server-pieces. Some of this glue I've - already reviewed proceeding for the components that use it; some - of it I haven't, and sooner or later I will, if only to establish - what's to stay and what's to go once I start cleaning the whole - thing up. - -[apache-mpm]: https://httpd.apache.org/docs/2.2/en/mpm.html -[ht-iii]: /posts/y06/097-hunchentoot-iii.html -[ht-iv]: /posts/y06/098-hunchentoot-iv.html -[ht-stt]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L127 -[ht-stt-ea]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L137 -[ht-stt-hic]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L141 -[ht-mtt]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L149 -[ht-mtt-ap]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L150 -[ht-mtt-ea]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L158 -[ht-otpct]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L175 -[ht-otpct-mtc]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L177 -[ht-otpct-mac]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L198 -[ht-otpct-wq]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L222 -[ht-otpct-ii]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L272 -[ht-otpct-itac]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L281 -[ht-otpct-dtac]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L286 -[ht-otpct-ittc]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L291 -[ht-otpct-dttc]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L296 -[ht-otpct-nfc]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L306 -[ht-otpct-wffc]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L311 -[ht-otpct-tmtr]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L317 -[ht-otpct-crht]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L322 -[ht-s3]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L345 -[ht-otpct-s3]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L348 -[ht-otpct-hic]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L354 -[ht-otpct-hic2]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L359 -[ht-otpct-ssur]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L392 -[ht-otpct-cas]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L416 -[ht-cvs]: http://coad.thetarpit.org/hunchentoot/c-compat.lisp.html#L132 -[ht-cvw]: http://coad.thetarpit.org/hunchentoot/c-compat.lisp.html#L135 -[ht-hcs]: http://coad.thetarpit.org/hunchentoot/c-conditions.lisp.html#L121 -[ht-s]: /posts/y06/098-hunchentoot-iv.html#s -[ht-s2]: /posts/y06/098-hunchentoot-iv.html#s2 -[ht-ac]: /posts/y06/098-hunchentoot-iv.html#ac -[ht-pc]: /posts/y06/098-hunchentoot-iv.html#pc -[ht-alm]: /posts/y06/098-hunchentoot-iv.html#alm -[ht-asm]: /posts/y06/098-hunchentoot-iv.html#asm -[ht-ifdefism]: /posts/y06/098-hunchentoot-iv.html#selection-195.296-199.206 -[tlogz-1926874]: http://logs.nosuchlabs.com/log/trilema/2019-08-09#1926874 -[clhs-up]: http://clhs.lisp.se/Body/s_unwind.htm -[tmsr-work-iv]: /posts/y06/099-tmsr-work-iv.html#selection-139.61-139.151 diff --git a/posts/y06/09b-hunchentoot-v.markdown b/posts/y06/09b-hunchentoot-v.markdown new file mode 100644 index 0000000..47e5fc9 --- /dev/null +++ b/posts/y06/09b-hunchentoot-v.markdown @@ -0,0 +1,298 @@ +--- +postid: 09b +title: Hunchentoot: taskmaster code review +date: August 16, 2019 +author: Lucian Mogoșanu +tags: tech, tmsr +--- + +This post is part of a series on [Common Lisp WWWism][cl-www], more +specifically of [ongoing work][hunchentoot-ii] to [saw +apart][hunchentoot-iii] Hunchentoot into pieces and [own][own] them +and the whole of this Common Lisp web server. The second fundamental +component of Hunchentoot, next to the so-called +[acceptor][hunchentoot-iv], is the so-called taskmaster. + +Hunchentoot taskmasters are, as the name suggests, an abstraction for +work management, or in other words, a mechanism implementing work +distribution among processing units. On the surface they look very +similar to Apache's [MPM][apache-mpm] model, which (again, viewed very +superficially) suggests Hunchentoot was an attempt at a Lisp-style +(re)implementation of Apache. This, as a side note, doesn't really +speak in its favour. We do know, however, what the current coad [is +made of][tlogz-1926027], and it's yet to be seen whether it can even +be retrofitted into something that fits in head, as it's otherwise by +all looks as usable as a [CL-on-Unix][alf-cl-on-pc]-on-top-of-TCP +application can be. It's not like there's a better [CL +item][mp-comment] to work with anyway, so that's that. + +As presented in the earlier [architectural overview][hunchentoot-iii], +taskmasters expose the following methods: execute-acceptor, +handle-incoming-connection and shutdown. In very broad lines, +execute-acceptor gets called on [start][ht-s] and sets up an execution +context where [accept-connections][ht-ac] is called; +handle-incoming-connection is then called on each new connection, +where it calls [process-connection][ht-pc]; and finally, shutdown is +called by [stop][ht-pc], in order to suspend request processing on all +threads. Additionally, (more specific) taskmasters may expose other +methods[^1] specific to their operation. + +The taskmaster class provides three subclasses: a single-threaded +implementation, an abstract "multi-threaded" taskmaster and a concrete +"one thread per connection" taskmaster descending from the +multi-threaded one -- otherwise the coad under examination is also +structured to accommodate the usual [ifdefisms][ht-ifdefism], which +we'll blissfully ignore. This being said, let us look at each +taskmaster and the method it implements. First, we notice that +shutdown is given an implementation for all taskmasters: + +[s3] [**shutdown**][ht-s3]: This is a +generic implementation, that can be (and is, in one case, as shown +below) overriden by subclasses; this implementation doesn't do +anything except returning the taskmaster object. + +**[[]]** [**single-threaded-taskmaster**][ht-stt]: The simplest +taskmaster implementation; probably not very useful for battlefield +use, because of poor load handling, [blocking +operations][tlogz-1926874] and so on. + +[stt-ea] +[**execute-acceptor**][ht-stt-ea]: Calls [accept-connections][ht-ac]. + +[stt-hic] +[**handle-incoming-connection**][ht-stt-hic]: Calls +[process-connection][ht-pc]. + +Shutdown is provided by the [generic implementation](#s3) above. + +**[[]]** [**multi-threaded-taskmaster**][ht-mtt]: Defines a new +[acceptor-process][ht-mtt-ap] field denoting a new thread whose sole +work is accepting new connections. Thus, this acceptor only provides +an implementation for: + +[mtt-ea] +[**execute-acceptor**][ht-mtt-ea]: Starts a new "listener" thread +which waits for new connections; essentially the same as [the +single-threaded version](#ht-stt-ea), only now accept-connections runs +on a separate thread. + +All the other methods are implemented by +sub-multi-threaded-taskmasters, i.e. by +one-thread-per-connection-taskmaster[^2]. + +**[[]]** [**one-thread-per-connection-taskmaster**][ht-otpct]: As the name +suggests, each new connection will spawn a new thread when it is to be +handled. Up to [max-thread-count][ht-otpct-mtc] connections are +accepted, and then the remaining connections up to +[max-accept-count][ht-otpct-mac] are [queued][ht-otpct-wq] waiting for +a thread to be allocated for them. If both counts are exceeded (or if +the former is exceeded and the latter is not set) then a HTTP 503 is +sent to the client. + +Below I'll detail (top-down) the implementation of +handle-incoming-connection, shutdown and (the additional) +initialize-instance -- the execute-acceptor in use is that of the +[father-class](#mtt-ea). + +[otpct-ii] +[**initialize-instance**][ht-otpct-ii]: This is an ":after" method +which, given a new taskmaster instance, does some sanity checking, +i.e. that: a. if max-accept-count is supplied, then so is +max-thread-count, and b. that the former is higher than the +latter. The idea here is that the number of Hunchentoot worker threads +is either unlimited[^3], or limited by max-thread-count -- in the +former case, max-accept-count doesn't really make sense, because new +connections never get blocked in the wait-queue. + +[otpct-hic] +[**handle-incoming-connection**][ht-otpct-hic]: Calls +[create-request-handler-thread](#otpct-crht); in other words, it +creates a new thread to handle requests associated with the current +connection. + +[otpct-s3] +[**shutdown**][ht-otpct-s3]: Joins (in the Unix sense of "thread +join") the acceptor-process, i.e. the [listener](#mtt-ea) thread and +returns the current taskmaster. + +As observed, these methods are implemented using the following +"support" methods and functions: + +[otpct-itac] +[**increment-taskmaster-accept-count**][ht-otpct-itac]: Atomically +increments the accept-count at a given time. + +[otpct-dtac] +[**decrement-taskmaster-accept-count**][ht-otpct-dtac]: Atomically +decrements the accept-count at a given time. + +[otpct-ittc] +[**increment-taskmaster-thread-count**][ht-otpct-ittc]: Atomically +increments the thread-count at a given time. + +[otpct-dttc] +[**decrement-taskmaster-thread-count**][ht-otpct-dttc]: Atomically +decrements the thread-count at a given time; when thread-count falls +under max-accept-count, notifies listener via +[note-free-connection](#otpct-nfc) that new connections may be +handled. + +[otpct-nfc] +[**note-free-connection**][ht-otpct-nfc]: [Signals][ht-cvs] the +taskmaster's wait-queue; as the name suggests, it's used when there +are "free" "slots" available for connections to be handled. + +[otpct-wffc] +[**wait-for-free-connection**][ht-otpct-wffc]: [Waits][ht-cvw] for +"free" connection "slots" on the taskmaster's wait-queue; used in +[handle-incoming-connection%](#otpct-hic2) when there aren't (yet) +enough resources to process a given connection. + +[otpct-tmtr] +[**too-many-taskmaster-requests**][ht-otpct-tmtr]: Calls +[acceptor-log-message][ht-alm]; logs the situation when the +taskmaster's wait-queue is full or, if max-accept-count isn't set, +that the thread-count has reached the ceiling i.e. max-thread-count. + +[otpct-crht] +[**create-request-handler-thread**][ht-otpct-crht]: a. Wrapped in a +[handler-case\*][ht-hcs]; b. start a new thread; c. which calls +[handle-incoming-connection%](#otpct-hic2). In case of errors, +d1. close the current connection's socket stream, aborting the +connection; and d2. [log][ht-lms] the error. + +[otpct-hic2] +[**handle-incoming-connection%**][ht-otpct-hic]: The description +contained in the function's definition is pretty good, but +nevertheless, let's look at this in more detail: +a. [increment-taskmaster-accept-count](#otpct-itac); b. create a local +binding for process-connection%, which b1. calls +[process-connection][ht-pc] b2. with the [thread-count +incremented](#otpct-ittc); c. implement the logic described below. + +c1. if thread-count is null, then [process-connection][ht-pc]; +otherwise, c2. *if* either max-accept-count is set and accept-count is +at this threshold, *or* max-accept-count isn't set and thread-count is +at the max-thread-count threshold, *then* call +[too-many-taskmaster-requests](#otpct-tmtr) and +[send-service-unavailable-reply](#otpct-ssur), which ends the current +connection; otherwise, c3. *if* max-accept-count is set *and* +thread-count is larger than max-thread-count *then* +[wait-for-free-connection](#otpct-wffc), then, when unblocked, +process-connection%; otherwise, c4. process-connection%. + +As can be observed, handle-incoming-connection% implements the bulk of +the decision-making process for one-thread-per-connection +taskmasters. This isn't *very* difficult to wrap one's head around, +despite the apparent gnarl; simplifications, at the very least of an +aesthetic nature, are possible, I'll leave them as a potential +exploration exercise for a later date -- or, if the reader desires to +chime in... + +[otpct-ssur] +[**send-service-unavailable-reply**][ht-otpct-ssur]: Yet another pile +of gnarl. Wraps everything in an [unwind-protect][clhs-up] and catches +all potential conditions. In this context, it sends a +http-service-unavailable message with the content set to the text +returned by [acceptor-status-message][ht-asm]. + +At the end, [decrement-taskmaster-accept-count](#otpct-dtac) and flush +and close the connection stream. + +[otpct-cas] +[**client-as-string**][ht-otpct-cas]: Convenience function used by +[create-request-handler-thread](#otpct-crht) to give a name to the +thread to be created, of the form "address:port". + +To conclude: as can be seen, this is still a monster, albeit more +organized than its [acceptor][hunchentoot-iv] brother. At this point, +the big remaining pieces are requests, replies and handler +dispatchers, which should provide us with almost[^4] everything we +need to actually have a Hunchentoot. + +Meta: blog comments are for now still missing; thus readers are +invited to leave them in [#spyked][contact] or (assuming they know +where they're heading) +#trilema. Existing comments are preserved here in [^5]. + +[^1]: Though all methods are piled together in the same place and, + say, default "thread count" implementations are provided for some + taskmasters that have nothing to do with multithreading. This is + IMHO a very early sign that whoever wrote the code must have been + fucked in the head. + +[^2]: Which isn't to say there couldn't be more than one + multi-threaded-taskmaster implementation, we just haven't seen any + others. The very same, however, could be said about e.g. shit: + sure, it could come from a human, a cow or a horse, but for all + intents and purposes it's still shit, so why the additional layer + of indirection? + + Oh, it could be extended? Well, show me one of these + extensions. And if there are any, why aren't they in Hunchentoot? + +[^3]: Which is in principle a very stupid idea, since computing + practice shows that resources are always limited, no matter how + many extra compute nodes or how much disk space, bandwidth + etc. you're willing to get. Then again, who's to say that the + webserver implementation oughta tell the operator how he should + run his program? + +[^4]: There's tons of [glue][tmsr-work-iv] poured around this set of + fundamentally TCPistic web-server-pieces. Some of this glue I've + already reviewed proceeding for the components that use it; some + of it I haven't, and sooner or later I will, if only to establish + what's to stay and what's to go once I start cleaning the whole + thing up. + +[^5]: No comments thus far. + +[ht-stt]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L127 +[ht-stt-ea]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L137 +[ht-stt-hic]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L141 +[ht-mtt]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L149 +[ht-mtt-ap]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L150 +[ht-mtt-ea]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L158 +[ht-otpct]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L175 +[ht-otpct-mtc]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L177 +[ht-otpct-mac]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L198 +[ht-otpct-wq]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L222 +[ht-otpct-ii]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L272 +[ht-otpct-itac]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L281 +[ht-otpct-dtac]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L286 +[ht-otpct-ittc]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L291 +[ht-otpct-dttc]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L296 +[ht-otpct-nfc]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L306 +[ht-otpct-wffc]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L311 +[ht-otpct-tmtr]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L317 +[ht-otpct-crht]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L322 +[ht-s3]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L345 +[ht-otpct-s3]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L348 +[ht-otpct-hic]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L354 +[ht-otpct-hic2]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L359 +[ht-otpct-ssur]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L392 +[ht-otpct-cas]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L416 +[ht-cvs]: http://coad.thetarpit.org/hunchentoot/c-compat.lisp.html#L132 +[ht-cvw]: http://coad.thetarpit.org/hunchentoot/c-compat.lisp.html#L135 +[ht-hcs]: http://coad.thetarpit.org/hunchentoot/c-conditions.lisp.html#L121 +[ht-s]: /posts/y06/098-hunchentoot-iv.html#s +[ht-s2]: /posts/y06/098-hunchentoot-iv.html#s2 +[ht-ac]: /posts/y06/098-hunchentoot-iv.html#ac +[ht-pc]: /posts/y06/098-hunchentoot-iv.html#pc +[ht-alm]: /posts/y06/098-hunchentoot-iv.html#alm +[ht-asm]: /posts/y06/098-hunchentoot-iv.html#asm +[ht-lms]: /posts/y06/098-hunchentoot-iv.html#lms +[ht-ifdefism]: /posts/y06/098-hunchentoot-iv.html#selection-195.296-199.206 +[cl-www]: /posts/y05/090-tmsr-work-ii.html#selection-108.0-108.17 +[hunchentoot-ii]: /posts/y05/096-hunchentoot-ii.html +[hunchentoot-iii]: /posts/y06/097-hunchentoot-iii.html +[hunchentoot-iv]: /posts/y06/098-hunchentoot-iv.html +[own]: /posts/y04/069-on-intellectual-ownership.html +[apache-mpm]: https://httpd.apache.org/docs/2.2/en/mpm.html +[tlogz-1926027]: http://logs.nosuchlabs.com/log/trilema/2019-08-01#1926027 +[alf-cl-on-pc]: http://trilema.com/2019/trilema-goes-dark/#comment-130686 +[mp-comment]: /posts/y06/098-hunchentoot-iv.html#comment3 +[tlogz-1926874]: http://logs.nosuchlabs.com/log/trilema/2019-08-09#1926874 +[clhs-up]: http://clhs.lisp.se/Body/s_unwind.htm +[tmsr-work-iv]: /posts/y06/099-tmsr-work-iv.html#selection-139.61-139.151 +[contact]: http://webchat.freenode.net/?channels=#spyked&nick=f_thetarpit_09b -- 1.7.10.4