Project

General

Profile

Feedback on lighttpd2

Added by s.gleissner about 6 years ago

Hello developers,

as promised here ( http://redmine.lighttpd.net/boards/2/topics/4571 ), i have some feedback on lighttpd2 for you...

We currently use lighttpd on an embedded platform, based on an ARM926EJ-S. Now we want to improve our fastcgi/AJAX-based application on that platform and i thought about distributing the same JSON data generated in shared memory for multiple clients. And there comes lighty2 into play.

As the new application is still in an early development phase, we additionally need a development environment. We are three developers, so i have configured three additional IP4 addresses on our development server and installed lighty2 on port 80 on that IPs, each one directed to a different web server directory. As the developers work on different projects at different times, the personal html root directories will change. It is not neccessary to change this during run-time, but perhaps lua can do this to enhance comfort.

I have compiled lighttpd2 for x86_64 under Suse Enterprise 11 SP1 (all neccessary packages installed from Suse repositories, including lua & openssl), without any problems.

I will cross-compile it for ARM926EJ-S under an older Linux Kernel 2.6 later (embedded platform, with openssl).

our plans include
- fastcgi to a C++ application (AJAX with late polling)
- openssl
- ipv6
so i think you will receive interesting feedback in the next time.

what i have found, so far:

A theoretical problem (and i do not really know if this is really a problem): i start lighty2 as root:root, but angel changes this to lighttpd:lighttpd (configured in angel.conf). Now i have touched two files access.log/error.log in /var/log/lighttpd2. I previously assumed that lighttpd opens these files as root before forking, but lighty2 can only write to them when they belong to lighttpd:lighttpd. If someone would break into lighty2 without root access, he could at least modify access.log/error.log. However, on the embedded platform, logging will be disabled.


I had a hang several times, when i tried to shut down the server with Ctrl-C (i do not start the server currently as a background daemon while testing):

2011-08-16 15:21:58 CEST: lighttpd2-worker[12646]: 16/Aug/2011 15:21:58 CEST 16/Aug/2011 15:21:58 CEST (debug) server.c.792: Reached state: running (dest: running)
^C2011-08-16 15:23:39 CEST: info (angel_plugin.c:168): activate
2011-08-16 15:23:39 CEST: info (angel_plugin.c:173): activate: core
2011-08-16 15:23:39 CEST: info (angel_plugin.c:179): done
2011-08-16 15:23:39 CEST: lighttpd2-worker[12646]: 16/Aug/2011 15:23:39 CEST 16/Aug/2011 15:23:39 CEST (debug) server.c.709: Try reaching state: suspending (dest: down)
2011-08-16 15:23:39 CEST: lighttpd2-worker[12646]: 16/Aug/2011 15:23:39 CEST (debug) server.c.792: Reached state: suspended (dest: down)
2011-08-16 15:23:39 CEST: lighttpd2-worker[12646]: 16/Aug/2011 15:23:39 CEST 16/Aug/2011 15:23:39 CEST (debug) server.c.792: Reached state: suspending (dest: down)
2011-08-16 15:23:39 CEST: lighttpd2-worker[12646]: 16/Aug/2011 15:23:39 CEST (debug) server.c.709: Try reaching state: stopping (dest: down)
2011-08-16 15:23:39 CEST: lighttpd2-worker[12646]: 16/Aug/2011 15:23:39 CEST 16/Aug/2011 15:23:39 CEST (debug) server.c.709: Try reaching state: suspended (dest: down)

But after a second ^C, it terminated. It's not easy to reproduce this behaviour.


I have defined several vhosts (mod_vhost is loaded). When i try to access the index.html on that vhost (here: miraculix-sg), i get an error 500 and an entry in error.log:

16/Aug/2011 16:35:34 CEST (error) plugin_core.c.442: no docroot specified yet but index action called

When i access this directory over the default docroot directive (here: miraculix-nr), it works.

On the console, i can see:

2011-08-16 16:09:28 CEST: lighttpd2-worker[15520]: 16/Aug/2011 16:09:28 CEST 16/Aug/2011 16:09:28 CEST (debug) mod_vhost.c.91: vhost_map: neither host miraculix-nr.dev.local found in hashtable nor default action specified, doing nothing
2011-08-16 16:35:34 CEST: lighttpd2-worker[15520]: 16/Aug/2011 16:35:34 CEST 16/Aug/2011 16:35:34 CEST (debug) mod_vhost.c.83: vhost_map: host miraculix-sg.dev.local found in hashtable

Here is the lighttpd.conf:

setup {

        module_load (
                "mod_accesslog",
                "mod_vhost" 
        );

        listen "192.168.0.125:80";
        listen "192.168.0.126:80";
        listen "192.168.0.127:80";

        log = ["debug": "", "*": "/var/log/lighttpd2/error.log"];
        accesslog = "/var/log/lighttpd2/access.log";
        accesslog.format = "%h %V %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"";

        include "/etc/lighttpd2/mimetypes.conf";

        static.exclude_extensions = ( ".php", ".pl", ".fcgi", "~", ".inc" );
}

vhost.debug = true;

miraculix_sg {
        index ( "index.html" );
        docroot "/srv/miraculix-sg";
}

#miraculix_nr {
#       index ( "index.html" );
#       docroot "/srv/miraculix-nr";
#}

#default_domain {
#       index ( "index.html" );
#       docroot "/srv/miraculix-default";
#}

vhost.map [
        "miraculix-sg.dev.local" : miraculix_sg,
        "miraculix-sg"           : miraculix_sg
#       "miraculix-nr.dev.local" : miraculix_nr,
#       "miraculix-nr"           : miraculix_nr,
#       "default"                : default_domain
];

docroot "/srv/miraculix-sg";
index ( "index.html" );
static;

So, if i uncomment either miraculix_nr or default_domain, it will not work at all. But with this configuration, access to miraculix-nr works.


... to be continued ...

Greetings,
Simon


Replies (17)

RE: Feedback on lighttpd2 - Added by spaam about 6 years ago

Yo.
You need to define index thing after docroot. like this:
miraculix_sg {
docroot "/srv/miraculix-sg";
index ( "index.html" );
}

RE: Feedback on lighttpd2 - Added by icy about 6 years ago

Hi, thanks for the feedback :)

I previously assumed that lighttpd opens these files as root before forking, but lighty2 can only write to them when they belong to lighttpd:lighttpd. If someone would break into lighty2 without root access, he could at least modify access.log/error.log.

This was true in 1.x but in 2.0 we open log files on the fly if needed. The reason for that is because we want to be able to change log files to any path e.g. depending on the request hostname and that's not possible at startup while being root. We could open it through the angel but I don't see much need for that.
If someone can break into lighty then he can change the log files no matter if they were opened as root or not, he could just re-use the open log file descriptors.

I had a hang several times, when i tried to shut down the server with Ctrl-C (i do not start the server currently as a background daemon while testing):
But after a second ^C, it terminated. It's not easy to reproduce this behavior

This is because the first SIGINT will make it shut down gracefully (waiting for all currently running requests to finish) and the second SIGINT will make the shutdown force closing all connections. A graceful shutdown should however not wait for keep-alive connections to time out. If you have a way to reproduce this, that would be nice.

As spaam said, you need to swap the docroot and index actions. The reason for this is that the index action immediately checks for the file and it has no docroot to work with yet at this point => error 500 cause lighty can't handle this any further.
This is a "downside" of the new config flow compared to 1.x (you need to care about the order of stuff in the config) but it on the other hand it brings a huge amount of flexibility which is well worth it.

Oh and btw, you don't need the static at the end of the config, the config parser inserts a static action automatically at the end :)

RE: Feedback on lighttpd2 - Added by s.gleissner about 6 years ago

Hi spaam, hello icy,

wow, that was fast. Thanks!!

Swapping docroot and index worked perfectly, and with the error 500 the hang went away. I have checked this, if i re-swap docroot and index for one vhost back to the wrong sequence and only if i try to load index.html from that host, i get the hang when terminating. So it seems to be the error 500...

By the way, i just have activated mod_fastcgi and reveived an (expected) error 503 (because the backend does not run), but then i got no hanging.

This is a "downside" of the new config flow compared to 1.x (you need to care about the order of stuff in the config) but it on the other hand it brings a huge amount of flexibility which is well worth it.

Well, i have no problems with this behaviour. A warning message would be nice (at startup console or error.log), someday perhaps...

I just changed the config to use vhost.map_regex, which also worked.

Tomorrow i will do the lua and fastcgi...

Greetings,
Simon

RE: Feedback on lighttpd2 - Added by icy about 6 years ago

The hanging is indeed caused by error 500 responses. The error handling code does not clean up the connection properly which makes it wait for the IO timeout (default 5min) to happen and will then exit.

I wont fix this right now as stbuehler is working on some core changes that touch this area and will probably fix it anyways.

Well, i have no problems with this behaviour. A warning message would be nice (at startup console or error.log), someday perhaps...

It's not so easy to spot this logic problem at config parse time. I think it would require some pretty big changes and even then I'm not sure if we could catch all such cases.
The index action does log a pretty specific error at request time and even in case one does not immediately see how to solve it, we can build a FAQ which explains it a bit more.

RE: Feedback on lighttpd2 - Added by s.gleissner about 6 years ago

Hello icy,

Oh and btw, you don't need the static at the end of the config, the config parser inserts a static action automatically at the end :)

Good, i have discarded it. I like small config files :-)

we can build a FAQ which explains it a bit more.

Yes, or include this in the wiki in the mod_vhost page at the examples, instead of "#... more config here ...". That was the point where i started when i implemented the vhosts.

i have some more feedback. After i had implemented fastcgi, i got a segfault:

miraculix:/etc # ~simon/start_lighttpd
2011-08-17 11:18:48 CEST: info (angel_plugin.c:168): activate
2011-08-17 11:18:48 CEST: info (angel_plugin.c:173): activate: core
2011-08-17 11:18:48 CEST: debug (angel_server.c:190): Instance (28769) spawned: /usr/local/libexec/lighttpd2/lighttpd2-worker
2011-08-17 11:18:48 CEST: info (angel_plugin.c:179): done
2011-08-17 11:18:48 CEST: info (angel_main.c:87): parsed config file
2011-08-17 11:18:48 CEST: lighttpd2-worker[28769]: 17/Aug/2011 11:18:48 CEST (debug) lighttpd_worker.c.106: config path: /etc/lighttpd2/lighttpd.conf
2011-08-17 11:18:48 CEST: lighttpd2-worker[28769]: 17/Aug/2011 11:18:48 CEST (debug) plugin_core.c.1202: loaded module 'mod_accesslog'
2011-08-17 11:18:48 CEST: lighttpd2-worker[28769]: 17/Aug/2011 11:18:48 CEST (debug) plugin_core.c.1202: loaded module 'mod_status'
2011-08-17 11:18:48 CEST: lighttpd2-worker[28769]: 17/Aug/2011 11:18:48 CEST (debug) plugin_core.c.1202: loaded module 'mod_vhost'
2011-08-17 11:18:48 CEST: lighttpd2-worker[28769]: 17/Aug/2011 11:18:48 CEST (debug) plugin_core.c.1202: loaded module 'mod_fastcgi'
2011-08-17 11:18:48 CEST: lighttpd2-worker[28769]: 17/Aug/2011 11:18:48 CEST (error) mod_fastcgi.c.135: Invalid socket address 'miraculix-sg.dev.local:9000'
2011-08-17 11:18:48 CEST: lighttpd2-worker[28769]: 17/Aug/2011 11:18:48 CEST (error) plugin.c.419: Action 'fastcgi' creation failed
2011-08-17 11:18:48 CEST: lighttpd2-worker[28769]: 17/Aug/2011 11:18:48 CEST (warning) config_parser.rl.1247: config parsing failed in line 39 of /etc/lighttpd2/lighttpd.conf
2011-08-17 11:18:48 CEST: error (angel_server.c:112): angel connection closed: eof
2011-08-17 11:18:48 CEST: error (angel_server.c:139): child 28769 died: killed by Segmentation fault
2011-08-17 11:18:48 CEST: error (angel_server.c:144): spawning child 28769 failed, not restarting
2011-08-17 11:18:48 CEST: info (angel_main.c:91): going down
2011-08-17 11:18:48 CEST: debug (angel_server.c:375): instance released

The problem is the hostname. I have exchanged this with its IP address, as the doc does not mention hostnames, just IPs.

miraculix_sg {
        if req.path =$ ".fcgi" {
                fastcgi "unix:/tmp/simon/fastcgi.sock";
        } else if req.path == "/ajax" or req.path == "/device" or req.path == "/upload" or req.path == "/download" {
#               fastcgi "miraculix-sg.dev.local:9000";     # does not work
                fastcgi "192.168.0.127:9000";              # works
        }
        docroot "/srv/miraculix-sg";
        index ( "index.html" );
}

Ok, the next segfault: when i start lighty2 with mod_fastcgi, let it run for about 30 seconds and then termiate it wich Ctrl-C, i get another segfault. During this, no pages are loaded from clients. If i terminate it just after startup, no segfault occurs:

miraculix:/etc # ~simon/start_lighttpd
2011-08-17 12:05:35 CEST: info (angel_plugin.c:168): activate
2011-08-17 12:05:35 CEST: info (angel_plugin.c:173): activate: core
2011-08-17 12:05:35 CEST: debug (angel_server.c:190): Instance (32128) spawned: /usr/local/libexec/lighttpd2/lighttpd2-worker
2011-08-17 12:05:35 CEST: info (angel_plugin.c:179): done
2011-08-17 12:05:35 CEST: info (angel_main.c:87): parsed config file
2011-08-17 12:05:35 CEST: lighttpd2-worker[32128]: 17/Aug/2011 12:05:35 CEST (debug) lighttpd_worker.c.106: config path: /etc/lighttpd2/lighttpd.conf
2011-08-17 12:05:35 CEST: lighttpd2-worker[32128]: 17/Aug/2011 12:05:35 CEST (debug) plugin_core.c.1202: loaded module 'mod_accesslog'
2011-08-17 12:05:35 CEST: lighttpd2-worker[32128]: 17/Aug/2011 12:05:35 CEST (debug) plugin_core.c.1202: loaded module 'mod_status'
2011-08-17 12:05:35 CEST: lighttpd2-worker[32128]: 17/Aug/2011 12:05:35 CEST (debug) plugin_core.c.1202: loaded module 'mod_vhost'
2011-08-17 12:05:35 CEST: lighttpd2-worker[32128]: 17/Aug/2011 12:05:35 CEST (debug) plugin_core.c.1202: loaded module 'mod_fastcgi'
2011-08-17 12:05:35 CEST: lighttpd2-worker[32128]: 17/Aug/2011 12:05:35 CEST (debug) config_parser.rl.1444: parsed config file in 0s, 2ms, 523us
2011-08-17 12:05:35 CEST: lighttpd2-worker[32128]: 17/Aug/2011 12:05:35 CEST (debug) server.c.792: Reached state: loading (dest: suspended)
2011-08-17 12:05:35 CEST: lighttpd2-worker[32128]: 17/Aug/2011 12:05:35 CEST (debug) server.c.709: Try reaching state: suspended (dest: suspended)
2011-08-17 12:05:35 CEST: lighttpd2-worker[32128]: 17/Aug/2011 12:05:35 CEST (debug) server.c.792: Reached state: suspended (dest: suspended)
2011-08-17 12:05:35 CEST: debug (angel_plugin_core.c:530): core_listen(0) '192.168.0.125:80'
2011-08-17 12:05:35 CEST: debug (angel_plugin_core.c:446): listen to ipv4: '192.168.0.125:80' (port: 80)
2011-08-17 12:05:35 CEST: debug (angel_plugin_core.c:530): core_listen(1) '192.168.0.126:80'
2011-08-17 12:05:35 CEST: debug (angel_plugin_core.c:446): listen to ipv4: '192.168.0.126:80' (port: 80)
2011-08-17 12:05:35 CEST: debug (angel_plugin_core.c:530): core_listen(2) '192.168.0.127:80'
2011-08-17 12:05:35 CEST: debug (angel_plugin_core.c:446): listen to ipv4: '192.168.0.127:80' (port: 80)
2011-08-17 12:05:35 CEST: lighttpd2-worker[32128]: 17/Aug/2011 12:05:35 CEST (debug) angel.c.73: listening on fd 7
2011-08-17 12:05:35 CEST: lighttpd2-worker[32128]: 17/Aug/2011 12:05:35 CEST (debug) angel.c.73: listening on fd 8
2011-08-17 12:05:35 CEST: lighttpd2-worker[32128]: 17/Aug/2011 12:05:35 CEST (debug) angel.c.73: listening on fd 9
2011-08-17 12:05:35 CEST: lighttpd2-worker[32128]: 17/Aug/2011 12:05:35 CEST (debug) server.c.709: Try reaching state: warmup (dest: running)
2011-08-17 12:05:35 CEST: lighttpd2-worker[32128]: 17/Aug/2011 12:05:35 CEST (debug) server.c.792: Reached state: warmup (dest: running)
2011-08-17 12:05:35 CEST: lighttpd2-worker[32128]: 17/Aug/2011 12:05:35 CEST (debug) server.c.709: Try reaching state: running (dest: running)
2011-08-17 12:05:35 CEST: lighttpd2-worker[32128]: 17/Aug/2011 12:05:35 CEST 17/Aug/2011 12:05:35 CEST (debug) server.c.792: Reached state: running (dest: running)
^C2011-08-17 12:06:04 CEST: info (angel_plugin.c:168): activate
2011-08-17 12:06:04 CEST: info (angel_plugin.c:173): activate: core
2011-08-17 12:06:04 CEST: info (angel_plugin.c:179): done
2011-08-17 12:06:04 CEST: lighttpd2-worker[32128]: 17/Aug/2011 12:06:04 CEST (debug) server.c.792: Reached state: suspended (dest: down)
2011-08-17 12:06:04 CEST: lighttpd2-worker[32128]: 17/Aug/2011 12:06:04 CEST (debug) server.c.709: Try reaching state: stopping (dest: down)
2011-08-17 12:06:04 CEST: lighttpd2-worker[32128]: 17/Aug/2011 12:06:04 CEST 17/Aug/2011 12:06:04 CEST (debug) server.c.709: Try reaching state: suspending (dest: down)
2011-08-17 12:06:04 CEST: lighttpd2-worker[32128]: 17/Aug/2011 12:06:04 CEST 17/Aug/2011 12:06:04 CEST (debug) server.c.792: Reached state: suspending (dest: down)
2011-08-17 12:06:04 CEST: lighttpd2-worker[32128]: 17/Aug/2011 12:06:04 CEST (debug) server.c.792: Reached state: stopping (dest: down)
2011-08-17 12:06:04 CEST: lighttpd2-worker[32128]: 17/Aug/2011 12:06:04 CEST 17/Aug/2011 12:06:04 CEST (debug) server.c.709: Try reaching state: suspended (dest: down)
2011-08-17 12:06:04 CEST: lighttpd2-worker[32128]: 17/Aug/2011 12:06:04 CEST (debug) server.c.709: Try reaching state: down (dest: down)
2011-08-17 12:06:04 CEST: lighttpd2-worker[32128]: 17/Aug/2011 12:06:04 CEST (debug) server.c.792: Reached state: down (dest: down)
2011-08-17 12:06:04 CEST: lighttpd2-worker[32128]: 17/Aug/2011 12:06:04 CEST (info) lighttpd_worker.c.142: going down
2011-08-17 12:06:04 CEST: error (angel_server.c:130): child 32128 died: killed by 'Segmentation fault' (11)
2011-08-17 12:06:04 CEST: debug (angel_server.c:375): instance released
2011-08-17 12:06:04 CEST: info (angel_main.c:91): going down

My full config. If i reduce it to one vhost, or to one fastcgi per vhost, i can not reproduce the failure:

setup {
        module_load (
                "mod_accesslog",
                "mod_status",
                "mod_vhost",
                "mod_fastcgi" 
        );

        listen "192.168.0.125:80";
        listen "192.168.0.126:80";
        listen "192.168.0.127:80";

        log = ["debug": "", "*": "/var/log/lighttpd2/error.log"];
        accesslog = "/var/log/lighttpd2/access.log";
        accesslog.format = "%h %V %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"";

        include "/etc/lighttpd2/mimetypes.conf";

        static.exclude_extensions = ( ".php", ".pl", ".fcgi", "~", ".inc" );
}

vhost.debug = true;

if req.path == "/server-status" {
        status.info;
}

miraculix_sg {
        if req.path =$ ".fcgi" {
                fastcgi "unix:/tmp/simon/fastcgi.sock";
        } else if req.path == "/ajax" or req.path == "/device" or req.path == "/upload" or req.path == "/download" {
                fastcgi "192.168.0.127:9000";
        }
        docroot "/srv/miraculix-sg";
        index ( "index.html" );
}

miraculix_jl {
        if req.path =$ ".fcgi" {
                fastcgi "unix:/tmp/julien/fastcgi.sock";
        } else if req.path == "/ajax" or req.path == "/device" or req.path == "/upload" or req.path == "/download" {
                fastcgi "192.168.0.125:9000";
        }
        docroot "/srv/miraculix-jl";
        index ( "index.html" );
}

miraculix_nr {
        if req.path =$ ".fcgi" {
                fastcgi "unix:/tmp/norbert/fastcgi.sock";
        } else if req.path == "/ajax" or req.path == "/device" or req.path == "/upload" or req.path == "/download" {
                fastcgi "192.168.0.126:9000";
        }
        docroot "/srv/miraculix-nr";
        index ( "index.html" );
}

default_domain {
        docroot "/srv/miraculix-default";
        index ( "index.html" );
}

vhost.map_regex [
        "^miraculix-sg(\.dev\.local)?$" : miraculix_sg,
        "^miraculix-jl(\.dev\.local)?$" : miraculix_jl,
        "^miraculix-nr(\.dev\.local)?$" : miraculix_nr,
        "default" : default_domain
];

I think, this might be one of those segfaults, which are hard to find. But i have a hint: none of the sockets (neither filesystem-socket, nor tcp port) are yet existing.

Greetings, Simon

RE: Feedback on lighttpd2 - Added by s.gleissner about 6 years ago

More feedback (you will like this one):

my colleage successfully built lighty2 for the ARM platform. And we were able to run our application with AJAX + long polling. Actually, some things are still disabled (classic CGI for some tools, some alias statements, set upload directory, set pid file, allow following symlinks), but it worked good.

RE: Feedback on lighttpd2 - Added by jlanger about 6 years ago

Hi there,

I'm Simon's collegue and we're currently playing around with lighty2 on ARM and already found the first problem :)

I have the following line in my configuration:

if req.path =$ ".fcgi" or req.path == "/device" or req.path == "/ajax" {
    fastcgi "unix:/tmp/fastcgi.sock";
}

Access to /*.fcgi and /ajax works, but accessing /device fails with 404.
If I exchange /device und /ajax in the above line, then calls to /device work but /ajax fails, so it looks like there's a problem parsing the configuration.

The problem disappears if I remove the req.path =$ ".fcgi" part from that line

thanks
Julien

RE: Feedback on lighttpd2 - Added by s.gleissner about 6 years ago

Hi,
i have an issue with lua. I want to set the docroot of a vhost in a lua script (this is my very first lua script, so i expect the error here, not in mod_lua):

-- personal.lua

local filename, args = ...

local function setdocroot(personal_vhost, personal_docroot)
  personal_vhost.docroot = personal_docroot
  return action.blank()
end

actions = {
        ["personal.setdocroot"] = setdocroot
}

My minimum config file is:

setup {
        module_load (
                "mod_vhost",
                "mod_lua",
                "mod_fastcgi" 
        );

        lua.plugin "/etc/lighttpd2/personal.lua";
        listen "192.168.0.127:80";
        include "/etc/lighttpd2/mimetypes.conf";
        static.exclude_extensions = ( ".php", ".pl", ".fcgi", "~", ".inc" );
}

miraculix_sg {
        if req.path =$ ".fcgi" {
                fastcgi "unix:/tmp/simon/fastcgi.sock";
        }
#       docroot "/srv/miraculix-sg";
#       index ( "index.html" );
}

personal.setdocroot (miraculix_sg,"/srv/miraculix-sg");

default_domain {
        docroot "/srv/miraculix-default";
        index ( "index.html" );
}

vhost.map_regex [
        "^miraculix-sg(\.dev\.local)?$" : miraculix_sg,
        "default" : default_domain
];

Wenn i start lighty2, i get:

miraculix:/etc/lighttpd2 # ~simon/start_lighttpd
2011-08-17 18:17:00 CEST: info (angel_plugin.c:168): activate
2011-08-17 18:17:00 CEST: info (angel_plugin.c:173): activate: core
2011-08-17 18:17:00 CEST: debug (angel_server.c:190): Instance (27035) spawned: /usr/local/libexec/lighttpd2/lighttpd2-worker
2011-08-17 18:17:00 CEST: info (angel_plugin.c:179): done
2011-08-17 18:17:00 CEST: info (angel_main.c:87): parsed config file
2011-08-17 18:17:00 CEST: lighttpd2-worker[27035]: 17/Aug/2011 18:17:00 CEST (debug) lighttpd_worker.c.106: config path: /etc/lighttpd2/lighttpd.conf
2011-08-17 18:17:00 CEST: lighttpd2-worker[27035]: 17/Aug/2011 18:17:00 CEST (debug) plugin_core.c.1202: loaded module 'mod_vhost'
2011-08-17 18:17:00 CEST: lighttpd2-worker[27035]: 17/Aug/2011 18:17:00 CEST (debug) plugin_core.c.1202: loaded module 'mod_lua'
2011-08-17 18:17:00 CEST: lighttpd2-worker[27035]: 17/Aug/2011 18:17:00 CEST (debug) plugin_core.c.1202: loaded module 'mod_fastcgi'
2011-08-17 18:17:00 CEST: lighttpd2-worker[27035]: 17/Aug/2011 18:17:00 CEST (debug) mod_lua.c.489: Loaded lua plugin '/etc/lighttpd2/personal.lua'
2011-08-17 18:17:00 CEST: lighttpd2-worker[27035]: 17/Aug/2011 18:17:00 CEST (error) mod_lua.c.339: lua_pcall(): /etc/lighttpd2/personal.lua:6: attempt to index local 'personal_vhost' (a userdata value)
2011-08-17 18:17:00 CEST: lighttpd2-worker[27035]: stack traceback:
2011-08-17 18:17:00 CEST: lighttpd2-worker[27035]:      /etc/lighttpd2/personal.lua:6: in function </etc/lighttpd2/personal.lua:5>
2011-08-17 18:17:00 CEST: lighttpd2-worker[27035]: 17/Aug/2011 18:17:00 CEST (error) plugin.c.419: Action 'personal.setdocroot' creation failed
2011-08-17 18:17:00 CEST: lighttpd2-worker[27035]: 17/Aug/2011 18:17:00 CEST (warning) config_parser.rl.1247: config parsing failed in line 22 of /etc/lighttpd2/lighttpd.conf
2011-08-17 18:17:00 CEST: error (angel_server.c:112): angel connection closed: eof
2011-08-17 18:17:00 CEST: error (angel_server.c:137): child 27035 died with exit status 1
2011-08-17 18:17:00 CEST: error (angel_server.c:144): spawning child 27035 failed, not restarting
2011-08-17 18:17:00 CEST: info (angel_main.c:91): going down
2011-08-17 18:17:00 CEST: debug (angel_server.c:375): instance released

As i see the problem, i can not access anything in my 'miraculix_sg' object. I also tried to uncomment the docroot line and to change the position of the personal.setdocroot directive, without success. When i change this line to 'personal.setdocroot ("miraculix_sg","/srv/miraculix-sg");' , then the error message of course changes.

Does anyone see an error in my script/config?

Greetings,
Simon

RE: Feedback on lighttpd2 - Added by s.gleissner about 6 years ago

Hello,

a small update to the complex req.path condition. I have exchanged this from

if req.path =$ ".fcgi" or req.path == "/device" or req.path == "/ajax" {
    fastcgi "unix:/tmp/fastcgi.sock";
}

to a regular expression
if req.path =~ "^/(.*\.fcgi|ajax|device|upload|download)$" {
        fastcgi "unix:/tmp/fastcgi.sock";
}

and now it works for us. Can it be the concatenated 'or' statements?

Greetings,
Simon

RE: Feedback on lighttpd2 - Added by icy about 6 years ago

So, if i uncomment either miraculix_nr or default_domain, it will not work at all. But with this configuration, access to miraculix-nr works.

I cannot follow you on that one. In the example config you gave there, you had "miraculix-sg.dev.local" and "default" commented out. So of course vhost.map can't find them. If I remove the comments, everything works fine so I don't think there is any issue unless I misunderstood you somehow.

The problem is the hostname. I have exchanged this with its IP address, as the doc does not mention hostnames, just IPs.

Correct, only IPs are supported. We don't want to resolve hostnames in the config. There are just too many issues that can arise from this. If it's absolutely needed then one can hack around with include_shell or use the lua config I guess.

I'm Simon's collegue and we're currently playing around with lighty2 on ARM and already found the first problem :)

Hi Simon, well good news is that Lighty2 apparently compiles on ARM which we didn't try at all. Hooray for portable C :)

Access to /*.fcgi and /ajax works, but accessing /device fails with 404.
If I exchange /device und /ajax in the above line, then calls to /device work but /ajax fails, so it looks like there's a problem parsing the configuration.

I have exchanged this from .. to a regular expression and now it works for us. Can it be the concatenated 'or' statements?

Yes, there was a bug in the config parser which made it not handle conditionals correctly when there was more than 2 in the same if.
I have pushed my changes to the config parser which change the syntax quite a bit and should also fix this problem.
I verified the following snippet working fine:

if req.path == "/a" or req.host == "b" and req.path =^ "/c" and req.path =$ "d" or req.path == "/e" or req.path == "/f" { log.write "if"; }
else if req.path =^ "/g" and req.path =$ "h" { log.write "elseif"; }
else { log.write "else"; }
The main changes are:
  • No more "=" for assignments. E.g. var.x = 1; becomes var.x 1;
  • "=>" instead of ":" in hashtables. E.g. ["foo" : "bar"] becomes ["foo" => "bar"]
  • User defined actions must now be prefixed with the "action" keyword. E.g. foo { ... } becomes action foo { ... }
  • Because of the change above, anonymous user defined actions don't need the *$* prefix anymore. E.g. var.x = ${ ... }; becomes var.x { ... };

However we are not 100% happy with this syntax yet. There will be more changes coming up (good we haven't released et :))

Please let me know if your problems disappear with those changes or if new bugs surface.

i have some more feedback. After i had implemented fastcgi, i got a segfault:

I was not able to reproduce this but maybe my config parser changes fixed this problem as a side effect. Please git pull and try again. If you should see the segfault still happening, please attach a gdb backtrace so I can look into it further.

Ok, the next segfault: when i start lighty2 with mod_fastcgi, let it run for about 30 seconds and then termiate it wich Ctrl-C, i get another segfault. During this, no pages are loaded from clients. If i terminate it just after startup, no segfault occurs:

Again I'm not able to reproduce this even though I copied your config 1:1. 30 seconds sounds like it has something to do with the logs which are kept open for 30s which would also explain why you don't see it if you terminate lighty right after startup. Can you get us a backtrace with gdb please?

i have an issue with lua. I want to set the docroot of a vhost in a lua script (this is my very first lua script, so i expect the error here, not in mod_lua):

Yes the issue is in your lua script. First you define a action that takes 2 parameters setdocroot(personal_vhost, personal_docroot), then you pass it an action as first parameter personal.setdocroot (miraculix_sg,"/srv/miraculix-sg"); and then you try to access a "docroot" member of the action object personal_vhost.docroot = personal_docroot. This can't work :)

Thanks for the feedback, keep it coming!

RE: Feedback on lighttpd2 - Added by jlanger about 6 years ago

Thanks for your answer!

I'm having a few issues with FastCGI. Our web application uses long polling, i.e. the browser sends a request which isn't handled by the application until there's new data to send to the browser. The browser periodically cancels the long polling request when it's not answered and then sends a new one.
If I understand the FastCGI spec correctly then lighty should send a FCGI_ABORT_REQUEST to the application to notify that the request is no longer valid but this doesn't seem to happen.

I currently work around this by keeping the active request for each logged in user and then cancel the previous request from within the fastcgi app when a user sends a new request. And there is the next issue:
I cancel the request by sending the FCGI_END_REQUEST packet without any STDOUT data. Lighty then logs the following error:
01/Jan/2000 05:54:06 UTC (error) mod_fastcgi.c.639: (unix:/tmp/fastcgi.sock) unexpected end-of-file (perhaps the fastcgi process die
I also tried to send an empty STDOUT packet followed by the END_REQUEST packet but that also results in this error.
These messages only disappear if I add some dummy STDOUT data to the packet. What's the correct way to handle this? The FastCGI spec doesn't seem to be clear about how to cancel an outstanding request from within the fastcgi application.

Please note that this happens both with lighty 1.4.26 and lighty 2

Thanks,
Julien

RE: Feedback on lighttpd2 - Added by s.gleissner about 6 years ago

So, if i uncomment either miraculix_nr or default_domain, it will not work at all. But with this configuration, access to miraculix-nr works.

I cannot follow you on that one. In the example config you gave there, you had "miraculix-sg.dev.local" and "default" commented out. So of course vhost.map can't find them.

Yes, the names i have choosen are a bit misleading.

If I remove the comments, everything works fine so I don't think there is any issue unless I misunderstood you somehow.

What i ment was: in the following configuration, access to miraculix_nr.dev.local worked, because of the default docroot at the end, which ist pointing to the directory /srv/miraculix-sg

miraculix_sg {
        index ( "index.html" );
        docroot "/srv/miraculix-sg";
}

#miraculix_nr {
#       index ( "index.html" );
#       docroot "/srv/miraculix-nr";
#}

#default_domain {
#       index ( "index.html" );
#       docroot "/srv/miraculix-default";
#}

vhost.map [
        "miraculix-sg.dev.local" : miraculix_sg,
        "miraculix-sg"           : miraculix_sg
#       "miraculix-nr.dev.local" : miraculix_nr,
#       "miraculix-nr"           : miraculix_nr,
#       "default"                : default_domain
];

docroot "/srv/miraculix-sg";
index ( "index.html" );

In this configuration, access to miraculix_nr.dev.local did not work. I got an Error 500 (and if i have to make a guess, i would say because of the multiple vhost links to miraculix-nr definiton block. After i changed that one to a single regexp, it worked.).

miraculix_sg {
        index ( "index.html" );
        docroot "/srv/miraculix-sg";
}

miraculix_nr {
       index ( "index.html" );
       docroot "/srv/miraculix-nr";
}

default_domain {
       index ( "index.html" );
       docroot "/srv/miraculix-default";
}

vhost.map [
        "miraculix-sg.dev.local" : miraculix_sg,
        "miraculix-sg"           : miraculix_sg
        "miraculix-nr.dev.local" : miraculix_nr,
        "miraculix-nr"           : miraculix_nr,
        "default"                : default_domain
];

docroot "/srv/miraculix-sg";
index ( "index.html" );

However, i gave it a try and changed it back, but with the new parser, it seems to work. At least there is no more Error 500, but now i have another issue. When i load doc/mimetypes.conf, the parser reminds about the "=" after mime_types:

mime_types = (
".ez" => "application/andrew-inset",
".anx" => "application/annodex",
(...)
);

But when i remove it, the mime types are no longer used correctly, e.g. loading miraculix_nr.dev.local downloads the index.html (instead of showing). I can not exchange the brackets () => [], because lighty2 wants the the mime_types keyword to get a list, not a hash:

2011-08-23 09:56:41 CEST: lighttpd2-worker[18421]: 23/Aug/2011 09:56:41 CEST (error) plugin.c.311: Unexpected value type 'hash', expected 'list' for option mime_types
2011-08-23 09:56:41 CEST: lighttpd2-worker[18421]: 23/Aug/2011 09:56:41 CEST (warning) config_parser.rl.1332: config parsing failed in line 481 of /etc/lighttpd2/mimetypes.conf
2011-08-23 09:56:41 CEST: lighttpd2-worker[18421]: 23/Aug/2011 09:56:41 CEST (warning) config_parser.rl.1332: config parsing failed in line 26 of /etc/lighttpd2/lighttpd2.conf

Do you also have a new syntax for mime_types? It yes, is not yet included in the doc folder.

Correct, only IPs are supported. We don't want to resolve hostnames in the config. There are just too many issues that can arise from this. If it's absolutely needed then one can hack around with include_shell or use the lua config I guess.

That's absolutely ok for us.

However we are not 100% happy with this syntax yet. There will be more changes coming up (good we haven't released et :))

No problem, we are not in a hurry.

Can you get us a backtrace with gdb please?

Sure, i will try to reproduce the problems with the new configuration.

Greetings,
Simon

RE: Feedback on lighttpd2 - Added by s.gleissner about 6 years ago

The main changes are:
  • "=>" instead of ":" in hashtables. E.g. ["foo" : "bar"] becomes ["foo" => "bar"]

looks like perl :-)

However we are not 100% happy with this syntax yet.

from the documentation:

value => value
Shortcut to create a list of two members.
15 => "foo" is equivalent to (15, "foo")

This syntax is used for mime_types and i think this is a bit confusing compared with the hashes. I have compared this with the lighty1 configuration. For me, it looks like you have introduced the hashes in lighty2 to abandon this two-member list syntax, but you're not yet finished ;-)

Greetings,
Simon

RE: Feedback on lighttpd2 - Added by stbuehler about 6 years ago

jlanger wrote:

I'm having a few issues with FastCGI. Our web application uses long polling, i.e. the browser sends a request which isn't handled by the application until there's new data to send to the browser. The browser periodically cancels the long polling request when it's not answered and then sends a new one.
If I understand the FastCGI spec correctly then lighty should send a FCGI_ABORT_REQUEST to the application to notify that the request is no longer valid but this doesn't seem to happen.

FCGI_ABORT_REQUEST for fastcgi keep-alive or multiplexed connections, or just closing the socket.

The problem here is that we stop reading from the http client after we got a request, and the only way to detect the browser cancelling the request would be to read (and get EOF).
I plan to implement this in 2.0 (wip: https://github.com/lighttpd/lighttpd2/tree/personal/stbuehler/streams), but in 1.x i won't fix this.

I currently work around this by keeping the active request for each logged in user and then cancel the previous request from within the fastcgi app when a user sends a new request. And there is the next issue:
I cancel the request by sending the FCGI_END_REQUEST packet without any STDOUT data. Lighty then logs the following error:
01/Jan/2000 05:54:06 UTC (error) mod_fastcgi.c.639: (unix:/tmp/fastcgi.sock) unexpected end-of-file (perhaps the fastcgi process die
I also tried to send an empty STDOUT packet followed by the END_REQUEST packet but that also results in this error.
These messages only disappear if I add some dummy STDOUT data to the packet. What's the correct way to handle this? The FastCGI spec doesn't seem to be clear about how to cancel an outstanding request from within the fastcgi application.

Another workaround is to send some "keep-alive" data - if the client closes the connection (not just shutdown) and we send more data, we will get a TCP RST resulting in ECONNRESET the next time we try to write.

RE: Feedback on lighttpd2 - Added by s.gleissner about 6 years ago

icy wrote:

However we are not 100% happy with this syntax yet. There will be more changes coming up (good we haven't released et :))
...
User defined actions must now be prefixed with the "action" keyword. E.g. foo { ... } becomes action foo { ... }

I just have pulled the actual code and found several changes. The mimetypes.conf seems to load now, but there were some (undocumented?) changes with the action blocks.

action miraculix_sg {
        if req.path =$ ".fcgi" {
                fastcgi "unix:/tmp/simon/fastcgi.sock";
        } else if req.path =~ "^/(ajax|device|upload|download)$" {
                fastcgi "192.168.0.127:9000";   # miraculix-sg.dev.local:9000
        }
        docroot "/srv/miraculix-sg";
        index   ( "index.html" );
}

action miraculix_jl {
        if req.path =$ ".fcgi" {
                fastcgi "unix:/tmp/julien/fastcgi.sock";
        } else if req.path =~ "^/(ajax|device|upload|download)$" {
                fastcgi "192.168.0.125:9000";   # miraculix_jl.dev.local:9000
        }
        docroot "/srv/miraculix-jl";
        index   ( "index.html" );
}

throws

2011-09-26 13:35:13 CEST: lighttpd2-worker[16504]: 26/Sep/2011 13:35:13 CEST (warning) config_parser.rl.1417: parse error in line 40 of "/etc/lighttpd2/lighttpd2.conf" at character ' ' (0x20)
2011-09-26 13:35:13 CEST: lighttpd2-worker[16504]: 26/Sep/2011 13:35:13 CEST (warning) config_parser.rl.1344: config parsing failed in line 40 of /etc/lighttpd2/lighttpd2.conf

which is in the "action miraculix_sg" line. When i delete both "action" keywords, i get

2011-09-26 13:38:27 CEST: lighttpd2-worker[16532]: 26/Sep/2011 13:38:27 CEST (warning) config_parser.rl.1417: parse error in line 50 of "/etc/lighttpd2/lighttpd2.conf" at character 'm' (0x6d)
2011-09-26 13:38:27 CEST: lighttpd2-worker[16532]: 26/Sep/2011 13:38:27 CEST (warning) config_parser.rl.1344: config parsing failed in line 50 of /etc/lighttpd2/lighttpd2.conf

note: the "at character 'm'" differs from the first error log. It seems that the action block definitons has changed again.

Greetings,
Simon

RE: Feedback on lighttpd2 - Added by icy about 6 years ago

Hi Simon,

there have been a few more changes:

  • You can't use includes or other setup blocks in a setup block (commit lighttpd2:cc1c9a92)
  • User defined variables now include actions and are defined via "x = y;" (commit lighttpd2:04c8356b)

Your config needs to look like this:

miraculix_sg = {
        if req.path =$ ".fcgi" {
                fastcgi "unix:/tmp/simon/fastcgi.sock";
        } else if req.path =~ "^/(ajax|device|upload|download)$" {
                fastcgi "192.168.0.127:9000";   # miraculix-sg.dev.local:9000
        }
        docroot "/srv/miraculix-sg";
        index   ( "index.html" );
};

miraculix_jl = {
        if req.path =$ ".fcgi" {
                fastcgi "unix:/tmp/julien/fastcgi.sock";
        } else if req.path =~ "^/(ajax|device|upload|download)$" {
                fastcgi "192.168.0.125:9000";   # miraculix_jl.dev.local:9000
        }
        docroot "/srv/miraculix-jl";
        index   ( "index.html" );
};

Not the last ";" after the blocks. It's easy to forget.

Feedback on this syntax would be appreciated.

RE: Feedback on lighttpd2 - Added by s.gleissner almost 6 years ago

Hello icy,

thanks for the fast answer.

icy wrote:

  • You can't use includes or other setup blocks in a setup block (commit lighttpd2:cc1c9a92)

Yes, i have found an error message that told me that (for the updated mimtypes.conf). No problem...

  • User defined variables now include actions and are defined via "x = y;" (commit lighttpd2:04c8356b)

I see. Does that mean that these variables can be redefined in a lua script?

Your config needs to look like this:

Yes, it works, thank you.

Feedback on this syntax would be appreciated.

Well, it is difficult to understand the differences in the syntax, like

vhost.map_regex [
        "^miraculix-sg(\.dev\.local)?$" => miraculix_sg,
        "^miraculix-jl(\.dev\.local)?$" => miraculix_jl,
        "^miraculix-nr(\.dev\.local)?$" => miraculix_nr,
        "default"                       => default_domain
];

or

setup {                                                                                
        mime_types (
                ".ez" => "application/andrew-inset",
                ".anx" => "application/annodex",    
                ".atom" => "application/atom+xml",
...
                "README" => "text/plain; charset=utf-8" 
        );
}

Ok, i think, my mistake is, that i expect that vhost.map_regex and mime_types are some kind of variables, but they are in fact commands that get exactly one argument: a list or a hash. What is irritating for me, is that the list is in parenthesis and looks like a multi-parameter function call and the hash uses [].

And i think, an action block is always unnamed. setup {...} is a command that gets an action block as single parameter. miraculix_sg = {...} is a variable, which is loaded with an action block.

Is that right? I mean, the syntax is non-ambiguous and very short, but its beauty is not really obvious.

Greetings
Simon

    (1-17/17)