On Sat 03 Sep 2022 at 10:23, nature <[email protected]> wrote:
> Then I tried something simpler like the echo server wrom
> rosettacode: https://rosettacode.org/wiki/Echo_server#Forth and this
> didn't work as well.
>
> I then tried to insert some ." at different places and I realized that
> create-server and accept-socket works, it's read-socket that
> fails/blocks indefinitely. When going deeper and trying to figure out
> where exactly in read-socket things were blocking, I found that it's the
> recv call that blocks/fails. I wasn't able to figure out more than
> that...
It seems that read-socket is trying to provide some kind of higher lever
blocking API I do not understand.
You can see the source code for read-socket with the following commands:
• (eepitch-shell)
• (eepitch-kill)
• (eepitch-shell)
gforth
require unix/socket.fs
view read-socket
view (rs)
Using read and write instead of read-socket and write-socket worked for
me, see the attached forking echo server example.
\ GOOD
\ TODO avoid pthread linking
\ gforth ./echo-server9.fs
\ (not needed anymore) GFORTHHIST=/no-history gforth ./echo-server9.fs
' noop IS bootmessage
\ ' noop IS 'cold \ still uses history file
warnings off
-status
include unix/socket.fs
\ include unix/libc.fs \ ?errno-throw
c-library wait
\c #include <sys/wait.h>
\c #define _WNOHANG() WNOHANG
c-function WNOHANG _WNOHANG -- n ( -- WNOHANG )
c-function waitpid waitpid n a n -- n ( pid_t *wstatus options -- pid_t )
\c #include <unistd.h>
c-function alarm alarm n -- void ( sec -- )
c-function (dup2) dup2 n n -- n ( oldfd newfd -- newfd )
\c #include <signal.h>
\c #define _sigchld() signal(SIGCHLD, SIG_IGN)
c-function -sigchld _sigchld -- void
end-c-library
: dup2 ( oldfd newfd -- ) (dup2) -1 = ?errno-throw ;
80 constant size
0 value %server
: echo ( -- )
BEGIN
2 alarm \ timeout after 2s inactivity
0 pad size read pad swap ( a u -- )
\ dup . errno .
dup 0>
WHILE
\ 2dup type
\ 2dup dump
>r >r 1 r> r> write \ TODO loop
REPEAT
drop drop ;
: parent ( socket -- ) close-socket ;
: child ( socket -- )
%server close-server
dup fileno dup 0 dup2 1 dup2 close-socket
['] echo catch drop bye ;
: zombies
BEGIN -1 0 WNOHANG waitpid 0> WHILE REPEAT ;
: serve
12345 create-server to %server
%server 8 listen
-sigchld
BEGIN
2 alarm \ timeout after 2s inactivity
zombies \ TODO test alarm to unblock accept-socket every 2s
%server accept-socket
0 alarm \ turn of alarm
[char] . emit
fork() dup 0< throw IF parent ELSE child THEN
AGAIN ;
:noname ['] serve catch drop bye ; is 'quit
\ history close-file drop