YottaDB / YDB

Mirrored from https://gitlab.com/YottaDB/DB/YDB
Other
76 stars 37 forks source link

Allow LISTENING sockets to be passed to other processes without hanging (through JOB command or LOCAL socket passing) #275

Closed nars1 closed 6 years ago

nars1 commented 6 years ago

Final Release Note

Description

Currently sockets can be passed from one mumps process to another process in two ways.

1) JOB command accepts INPUT, OUTPUT and ERROR which can point to a SOCKET handle that is then inherited as $PRINCIPAL (i.e. stdin/stdout/stderr) respectively by the jobbed off process.

2) Passing of socket handles using WRITE /PASS and WRITE /ACCEPT across two processes.

In either case, if the passed socket is in the LISTENING state (as indicated by $KEY), things don't work currently but instead it hangs (things work only if a connection has been ESTABLISHED). This issue is to make socket passing work for the LISTENING state sockets too.

Below are test programs that illustrate the issue using both the above ways.

> cat socketJobPassListening.m
        ; Example M program to demonstrate passing a LISTENing socket to a child through JOB command
        ; Both STDIN and STDOUT can be passed to the child (through INPUT and OUTPUT jobparameters).
        ;
        set s="socket"
        open s:::"SOCKET"       ; create a SOCKET device
        open s:(LISTEN="socket1:LOCAL":ATTACH="handle1")::"SOCKET"      ; create a listening socket
        use s:(detach="handle1")                                        ; move listening socket to "socketpool" device
        job child:(INPUT="SOCKET:handle1":OUTPUT="SOCKET:handle1":ERROR="a1.mje")       ; job a child and make it inherit
                                                                                        ; the listening socket as its stdin/stdout
        open s:(CONNECT="socket1:LOCAL":DELIMITER=$c(10))::"SOCKET"     ; connect to listening socket that child inherited
        use s
        for  read cmdop($incr(i))  quit:$device         ; read data written by child from the socket
        use $principal
        zwrite cmdop                                    ; display data written by child in parent
        quit
child   ;
        ; Establish a CONNECTION in the listening socket passed in as $principal
        write /wait
        ; Write to this socket some data that will be read (and displayed) by the parent
        for i=1:1:5  write "This is the child writing Line ",i," out of 5 lines",!
        quit
> cat socketLocalPassListening.m
        ; Example M program to demonstrate passing a LISTENing socket to a child through a LOCAL socket
        ;
        set s="socket"
        open s:::"SOCKET"       ; create a SOCKET device in parent
        open s:(LISTEN="socket1:LOCAL":ATTACH="handle1")::"SOCKET"      ; create a listening socket "socket1"
        use s:(detach="handle1")                                        ; move listening socket to "socketpool" device
        job child                                                       ; job off child to pass the listening socket
        open s:(LISTEN="socket2:LOCAL":ATTACH="handle2")::"SOCKET"      ; create a new listening socket "socket2"
        use s
        write /wait                                                     ; establish a connection with child on "socket2"
        write /pass(,,"handle1")                                        ; pass the listening "socket1" socket through "socket2"
                                                                        ; now child owns the "socket1" listening socket
        open s:(CONNECT="socket1:LOCAL":DELIMITER=$c(10))::"SOCKET"     ; connect to listening "socket1" on child
        use s
        for  read cmdop($incr(i))  quit:$device         ; read data written by child from the socket
        use $principal
        zwrite cmdop                                    ; display data written by child in parent
        quit
child   ;
        set s="socket"                                  ; create a SOCKET device in child
        open s:(CONNECT="socket2:LOCAL")::"SOCKET"      ; connect to "socket2" listening socket in parent
        use s
        write /accept(.handle,,,)                       ; accept the listening "socket1" socket from parent
        use s:(attach=handle)
        write /wait                                     ; wait for a connection from parent to come on "socket1" listening socket
        use s:(delimiter=$c(10))                        ; set delimiters explicitly since they are not inherited in passed sockets
        ; Write to this socket some data that will be read (and displayed) by the parent
        for i=1:1:5  write "This is the child writing Line ",i," out of 5 lines",!
        quit

Draft Release Note

Sockets in LISTENING state can now be passed to other processes using a) JOB command or b) WRITE /PASS and WRITE /ACCEPT. Previously this used to hang.