Re: [hackers] [quark] Make the serving process interruptible || Laslo Hunhold

2020-10-11 Thread Laslo Hunhold
On Wed, 7 Oct 2020 11:22:24 -0700
Anselm Garbe  wrote:

Dear Anselm,

thanks for your feedback!

> Do you really think the world needs another poll or select based web
> server?

Actually the forking model is the most common, from what I've seen.

> The beauty of quark (as implied by its name) is the pure simplicity
> and hackability it may provide. What's wrong with fork()? Aren't
> processes and threads pretty much the same these days? What real
> problem do you intend to fix with running everything from the same
> process and introducing threads etc. when Unix fixed this problem 40
> years ago already by introducing processes.

Handling processes is quirky and the static nature of quark opens a new
approach to handle connections. It's not visible now, as I haven't
pushed the changes yet, but let's discuss this once they are mainlined.

> Wasn't the idea behind quark to have a clear purpose, to easily maybe
> proxy or embed some scripts on top of http, to just serve some static
> content from a random directory for a limited time? Kind of the
> counterpart of curl, maybe allowing you to build a proxying tee for
> some debugging as apache/tomcat/etc. and other such monsters cannot
> easily be debugged anymore?
> 
> Or in other words are we still on the right track?
> 
> Isn't suckless all about sticking to the paradigms that have proven
> during time? If fork() ain't good enough, then fix the process model
> of your kernel instead ;)

You bring up really good points and I, of course, heavily weighed them
in the process. The interesting thing about quark, I think, is that
it's possible to run a server in constant memory without any mallocs at
runtime. A fork() can fail when resources are exhausted, but if you
have worker-threads, you have full control over the process and are not
susceptible to really low-hanging attacks like the HTTP-sloth, which
you can, though, handle much better in a shared connection "pool".

Sure, it adds a small overhead, because you launch a thread pool in a
few lines, but it allows much finer control (if you desire) over
quark's resource-usage. The proclimit really wasn't explicit enough and
could lead to runtime-limits. When the changes are done, quark will
allocate all it needs on startup and then never ask for anything ever
again (except for dirlistings, which you can disable and have a
reasonable resource-usage that is "guaranteed" by the kernel).

With best regards

Laslo



Re: [hackers] [quark] Make the serving process interruptible || Laslo Hunhold

2020-10-07 Thread Anselm Garbe
Hi Laslo,

Do you really think the world needs another poll or select based web server?

The beauty of quark (as implied by its name) is the pure simplicity
and hackability it may provide. What's wrong with fork()? Aren't
processes and threads pretty much the same these days? What real
problem do you intend to fix with running everything from the same
process and introducing threads etc. when Unix fixed this problem 40
years ago already by introducing processes.

Wasn't the idea behind quark to have a clear purpose, to easily maybe
proxy or embed some scripts on top of http, to just serve some static
content from a random directory for a limited time? Kind of the
counterpart of curl, maybe allowing you to build a proxying tee for
some debugging as apache/tomcat/etc. and other such monsters cannot
easily be debugged anymore?

Or in other words are we still on the right track?

Isn't suckless all about sticking to the paradigms that have proven
during time? If fork() ain't good enough, then fix the process model
of your kernel instead ;)

Thanks,
Anselm



Re: [hackers] [quark] Make the serving process interruptible || Laslo Hunhold

2020-10-05 Thread Laslo Hunhold
On Sun, 4 Oct 2020 07:06:51 -0700
Jeremy  wrote:

Dear Jeremy,

thanks for your feedback!

> Thanks to this patch, I've realized that there were two design
> desicions made, which make quark easy to hack on, and easy to
> maintain: 1. Each resp_* function wrote 100% of the HTTP response
>   2. Each request is handled in a new process
> 
> 1: Not only does this make it easier to read, but it also allows
> an end user-developer to to:
>   - add their own non-standard header
>   - offload the the response generation to a different program,
> a program that may set the "Content-Type" or "Set-Cookie"
> headers

Yes, even though it has its limits of course.

> 2: Forking for each request allows the end user-developer to manage
> connections as he/she sees fit, while building on their existing
> knowledge of process management.

This is just a remnant and will be changed later. I actually have quite
a lot of commits "lined up", which I haven't pushed, as I want to
handle sloth attacks better.

> Here's how I might prevent sloth attacks(this should kill children of
> quark that are >10 seconds old):
> 
> ps --ppid $QUARK_PID -oetimes,pid | awk 'NR!=1 && $2 > 10 { print $2
> }' |
> > xargs kill  
> 
> The command is not the important part, but that by using a well-known
> process management interface, I can manage connections the way I like.
> 
> I believe that if one didn't want to use fork(3), while also keeping
> the simplicity of quark, that person should rewrite quark in Golang.
> 
> I look forward to your feedback.

Stay tuned for the upcoming changes, which implement worker threads
using epoll. In the case of a sloth attack, I want to implement it in a
way that each thread can look at its list of active connections and
select an offender to "drop" (e.g. first determine the IP-address from
which most requests originate or look at the total connection age or
the time since last activity). I like the idea of using external tools
to drop connections, but the forking-model, imho, just doesn't scale
well enough and I wanted a challenge. :)

Thanks again for your elaborate feedback, I really appreciate it! Stay
tuned for the upcoming changes.

With best regards

Laslo



Re: [hackers] [quark] Make the serving process interruptible || Laslo Hunhold

2020-10-04 Thread Jeremy
Hey Laslo,

On 09/14/20 02:56PM, g...@suckless.org wrote:
> Make the serving process interruptible
> 
> Given the static nature of quark, I wanted to try something out that
> is not really possible with a "dynamic" server: Making the serving
> process interruptible in constant memory (except dir-listings of
> course). This can easily be extended to a polling architecture later
> on, but it most importantly warrants a non-blocking I/O scheme and
> makes the server more or less immune to sloth attacks (i.e. clients
> sending requests very slowly), and provides a more flexible approach to
> connections. Any thread can pick up a connection and continue work on
> it, without requiring a separate process for each (which might hit the
> forking limit at some point). If we hit a point where all connections
> are busy (due to many sloth attacks), one can apply arbitrary complex
> logic to "cancel" connections that show malicious behaviour (e.g. taking
> a long time to send the request header, etc.).
> 

Thanks to this patch, I've realized that there were two design desicions
made, which make quark easy to hack on, and easy to maintain:
1. Each resp_* function wrote 100% of the HTTP response
2. Each request is handled in a new process

1: Not only does this make it easier to read, but it also allows
an end user-developer to to:
- add their own non-standard header
- offload the the response generation to a different program,
  a program that may set the "Content-Type" or "Set-Cookie"
  headers

2: Forking for each request allows the end user-developer to manage
connections as he/she sees fit, while building on their existing knowledge
of process management.

Here's how I might prevent sloth attacks(this should kill children of
quark that are >10 seconds old):

ps --ppid $QUARK_PID -oetimes,pid | awk 'NR!=1 && $2 > 10 { print $2 }' |
>   xargs kill

The command is not the important part, but that by using a well-known
process management interface, I can manage connections the way I like.

I believe that if one didn't want to use fork(3), while also keeping
the simplicity of quark, that person should rewrite quark in Golang.

I look forward to your feedback.

Jeremy