[Libwebsockets] CGI on lws

Andy Green andy at warmcat.com
Thu Feb 25 04:07:49 CET 2016

On 02/25/2016 12:43 AM, Andy Green wrote:
> On 02/24/2016 05:44 AM, Andy Green wrote:
>> On February 24, 2016 12:00:24 AM GMT+08:00, James Stormes
>> <jstormes at stormes.net> wrote:
>>> Andy,
>>> This is exactly what I am waiting for.  I work mostly in ASP C#
>>> and/or PHP and need to connect live data updates on the server to
>>> javascript.  My current best practice is long poll AJAX, but
>>> scalability is an issue.
>>> What I am looking for, and time permitting trying to build, is all
>>> the plumbing.  What you are doing can takes us a long way to
>>> connecting PHP on the server to JavaScript in the browser via web
>>> sockets.
>>> My suggestion is to build out enough to get connected to something
>>> like PHP and get some example code working so we can start finding
>>> issues in the design, and developing the techniques and best
>>> practice in the higher level languages.
>> Yes, he can already run arbitrary apps (eg, /bin/sh -c "cat
>> /proc/meminfo") and send the output on http in the test server, with
>> some example CGI env vars set.  I'll wire up POST to stdin and then
>> start pushing it on master.  I guess there are still many things to
>> get right, like timing out subprocesses, reaping children robustly,
>> corner cases etc, so somebody testing it and/or sending patches is
>> very welcome.
> I pushed what I have on master
> https://github.com/warmcat/libwebsockets/commit/7abdb536a5a0682720cf29cf2bd04be16caa60f3
> This is still using fork(), vfork() needs some other way to do both the
> redirection and environment setting.  You need to enable it in cmake

I converted it to vfork() and repushed that patch on master.

vfork() seems to be a bit mysterious if you google it, but actually his 
deal doesn't seem that bad:

  1) if you do a vfork() you are promising an exec*() call in the child

  2) for the parent process the period between vfork() and the exec*() 
is atomic (he's frozen)

  3) during that period any changes you make in your process memory are 
illegally reflected in the parent (you are actually sharing his 
pagetables illegally, that's why he's frozen)

  4) however changes to kernel state tied to the process don't count, 
eg, dup2() or close() that just syscall through to get the job done.

  5) the gain from that is the kernel can skip making a copy of the 
parent pagetables for the child process that you are anyway going to 
immediately discard when you do the exec*()

Basically it meant do the environment preparation in the parent and 
apply it in the child.  The redirection continues to work OK after the 

And doing the env by hand is better anyway, since it removes everything 
that would otherwise be inherited from the system / parent env except 
what we add.


> $ cmake .. -DLWS_WITH_CGI=1
> He adds a test bash script
> $ cat ../test-server/lws-cgi-test.sh
> #!/bin/sh
> echo "lwstest script stdout"
>  >&2 echo "lwstest script stderr"
> if [ "$REQUEST_METHOD" = "POST" ] ; then
>      read line
>      echo "read=\"$line\""
> fi
> echo "done"
> exit 0
> that is executed when you run the test server and visit
> http://localhost:7681/cgitest
> If he was executed with GET like that, he outputs on stdout -> http
> lwstest script stdout
> done
> If the script sees he was executed by POST, he waits for a line of text
> to come.  You can test that with
> $ echo hello > hello.txt
> $ wget http://localhost:7681/cgitest --post-file=hello.txt -O- --quiet
> lwstest script stdout
> read="hello"
> done
> The stderr output of the script goes on the lws log.
> -Andy
>> -Andy
>>> *James Stormes* *Software Developer* (817) 676-4291 (Cell)
>>> www.stormes.net
>>> Zend Certified Engineer
>>> <http://www.zend.com/en/yellow-pages/ZEND026190>
>>> On Tue, Feb 23, 2016 at 5:06 AM, Andy Green <andy at warmcat.com>
>>> wrote:
>>>> Hi -
>>>> I am working on adding a cmake-selectable CGI api to lws,
>>>> basically
>>>> LWS_VISIBLE LWS_EXTERN int lws_cgi(struct lws *wsi, char * const
>>>> *exec_array);
>>>> LWS_VISIBLE LWS_EXTERN int lws_cgi_kill(struct lws *wsi);
>>>> where the forked process' stdin/out/err is piped on to three
>>>> slave
>>> wsi
>>>> created in the same service thread as the master: these are
>>>> managed
>>> through
>>>> the same event loop as everything else, when the process has
>>>> output,
>>> his
>>>> pipe fd POLLIN fires and there's a user callback where the user
>>>> code
>>> can
>>>> wire it up to outputting it when the sink socket is writeable.
>>>> That happens piecemeal and multitasked according to the
>>>> combination of
>>> server,
>>>> network and process conditions; the user code in the callback
>>>> can
>>> choose to
>>>> wire it up to http[s] or ws[s] according to what they want.
>>>> The guts of it work already in my local tree, but there are quite
>>>> a
>>> lot of
>>>> things to take care about with regard to managing the event loop
>>> properly
>>>> for all cases, as well as deal with POST -> stdin and that might
>>>> take
>>> a
>>>> while.
>>>> The goal of it is to provide a primitive with which you can
>>>> easily
>>> spawn
>>>> "io-encapsulated" subprocesses to the network, ie, run cgi like
>>> mailman or
>>>> general scripts or web language interpreters.
>>>> I am curious if potential users of it have any comments or
>>> suggestions
>>>> about this direction, since it's one of decreasing number of
>>>> missing
>>> bits
>>>> in the lws toolkit from the point of view of it being able to
>>>> make a generic webserver.
>>>> -Andy _______________________________________________
>>>> Libwebsockets mailing list Libwebsockets at libwebsockets.org
>>>> http://libwebsockets.org/mailman/listinfo/libwebsockets
>> _______________________________________________ Libwebsockets mailing
>> list Libwebsockets at libwebsockets.org
>> http://libwebsockets.org/mailman/listinfo/libwebsockets
> _______________________________________________
> Libwebsockets mailing list
> Libwebsockets at libwebsockets.org
> http://libwebsockets.org/mailman/listinfo/libwebsockets

More information about the Libwebsockets mailing list