Dear Genodians,
we have a scenario where a java application reads from stdin and writes to stdout and stderr. In our current implementation a component provides a terminal session and a log session to where the jvm connects stdin, stdout and stderr accordingly. The java application needs to know when the input of data on stdin is finished. From the java applications perspective this is easiest done by reading until a EOF signal is received.
So a first tempting approach to this problem would be to extend the Terminal session interface with a signal handler for EOF. However... I'm hesitant to touch such a prominent session.
Is there an other approach to this? Maybe using the newly released vfs pipe plugin? Or via emulation of POSIX signals?
Yours truly, Sid
Hi Sid,
On 04.12.19 15:29, Sid Hussmann wrote:
So a first tempting approach to this problem would be to extend the Terminal session interface with a signal handler for EOF. However... I'm hesitant to touch such a prominent session.
Is there an other approach to this? Maybe using the newly released vfs pipe plugin? Or via emulation of POSIX signals?
this question reminds me to a very similar problem I had to solve for the graphical terminal in Sculpt. When clicking on the close button of a terminal window, I wanted to gracefully exit the Noux runtime that is connected to the terminal by reflecting the condition as EOF to the Noux application.
I solved it by using the existing 'size_changed_sigh' mechanism, which allows a terminal client to install a signal handler that is invoked each time the terminal size changes. Once the client receives the signal, it can request the new dimensions via the 'size' RPC function. The returned size is a tuple of (columns,rows) e.g., (80x25). A size of (0,0) implies that the terminal window got closed. This condition is used by Noux to feed the EOF to the Noux application. You can find the corresponding code at [1].
[1] https://github.com/genodelabs/genode/blob/master/repos/ports/src/noux/termin...
By the way, the same pattern is used by the framebuffer-session interface to gracefully wind down a framebuffer client when displayed in a window.
Would you be fine with following this path in your terminal server, sending the EOF as a terminal-size change to (0,0)?
Cheers Norman
Hi Norman,
On 12/6/19 11:02 AM, Norman Feske wrote:
I solved it by using the existing 'size_changed_sigh' mechanism, which allows a terminal client to install a signal handler that is invoked each time the terminal size changes. Once the client receives the signal, it can request the new dimensions via the 'size' RPC function. The returned size is a tuple of (columns,rows) e.g., (80x25). A size of (0,0) implies that the terminal window got closed. This condition is used by Noux to feed the EOF to the Noux application. You can find the corresponding code at [1].
[1] https://github.com/genodelabs/genode/blob/master/repos/ports/src/noux/termin...
By the way, the same pattern is used by the framebuffer-session interface to gracefully wind down a framebuffer client when displayed in a window.
Would you be fine with following this path in your terminal server, sending the EOF as a terminal-size change to (0,0)?
Thank you for your suggestion. While I like the idea of using the terminal size {0,0} as a way to communicate end of data, I'm not sure if it's applicable in my case. Let me draw up my scenario in init config snippets:
``` <start name="java" caps="300"> <resource name="RAM" quantum="96M"/> <config> <libc stdin="/dev/terminal" stdout="/dev/terminal" stderr="/dev/log"/> <arg value="/bin/java" /> ... </config> <route> <any-service> <any-child/> <parent/> </any-service> </route> </start>
<start name="my-terminal-server" caps="300"> <resource name="RAM" quantum="8M"/> <provides> <service name="Terminal"/> <service name="LOG"/> </provides> <config> <libc stdout="/dev/log" stderr="/dev/log" rtc="/dev/rtc"/> <policy label="java -> terminal"/> <policy label="java -> stderr"/> </config> </start> ```
So, the way I see it in this case, I'm not really in control of the Terminal client. Or, if I understand you correctly, I would have to change the libc implementation by handling the `size_changed_sigh` and if the new size is {0,0} I would emulate a EOF signal to the jvm. While I'm hesitant changing the Terminal session, I'm even more hesitant to extend libc with this workaround. Just to emphasize my case a bit more. I'm not in control of the Java application. The Java application is expected to handle stdin and stdout in a request/respond kind of way. So the EOF signal from the Java applications perspective is not used to gracefully shutdown itself, but to know when no more data is transferred. Does the combination of the posix runtime and a terminal or pipe connection to it not call for a EOF signal?
Best, Sid
Hi Sid,
Thank you for your suggestion. While I like the idea of using the terminal size {0,0} as a way to communicate end of data, I'm not sure if it's applicable in my case. Let me draw up my scenario in init config snippets:
there are two questions. First, how to communicate the EOF condition from the terminal server to the terminal client? Second, how to handle the EOF at the terminal client side (respectively the libc)?
My suggestion referred only to the first one (because your original question was about how to transport the EOF). You are right that the second part is still open. In contrast to Noux, the Vfs::Terminal_file_system [1] does not yet handle EOF.
[1] https://github.com/genodelabs/genode/blob/master/repos/os/src/lib/vfs/termin...
So, the way I see it in this case, I'm not really in control of the Terminal client. Or, if I understand you correctly, I would have to change the libc implementation by handling the `size_changed_sigh` and if the new size is {0,0} I would emulate a EOF signal to the jvm. While I'm hesitant changing the Terminal session, I'm even more hesitant to extend libc with this workaround.
Don't be afraid. It's not that bad. ;-) All that is missing is the handling of the special case of mode (0,0) in the VFS terminal fs linked above. At the VFS an EOF is signaled to the VFS client (e.g., the libc) by a successful return of read with 0 characters. I recently implemented the EOF handling for the VFS pipe plugin and think that the VFS terminal fs can follow the same pattern.
[2] https://github.com/genodelabs/genode/blob/master/repos/gems/src/lib/vfs/pipe...
Just to emphasize my case a bit more. I'm not in control of the Java application. The Java application is expected to handle stdin and stdout in a request/respond kind of way. So the EOF signal from the Java applications perspective is not used to gracefully shutdown itself, but to know when no more data is transferred. Does the combination of the posix runtime and a terminal or pipe connection to it not call for a EOF signal?
EOF is not a signal at the libc level. It is just a successful read of 0 characters.
I think that filling the current gap in the vfs/terminal_file_system.h should perfectly solve your issue. If you are hesitant, I can give it a go later this week.
Cheers Norman
Hi Norman,
there are two questions. First, how to communicate the EOF condition from the terminal server to the terminal client? Second, how to handle the EOF at the terminal client side (respectively the libc)?
My suggestion referred only to the first one (because your original question was about how to transport the EOF). You are right that the second part is still open. In contrast to Noux, the Vfs::Terminal_file_system [1] does not yet handle EOF.
You are right. These are two questions. I expected the client part to be more challenging...
Don't be afraid. It's not that bad. ;-) All that is missing is the handling of the special case of mode (0,0) in the VFS terminal fs linked above. At the VFS an EOF is signaled to the VFS client (e.g., the libc) by a successful return of read with 0 characters. I recently implemented the EOF handling for the VFS pipe plugin and think that the VFS terminal fs can follow the same pattern.
[2] https://github.com/genodelabs/genode/blob/master/repos/gems/src/lib/vfs/pipe...
EOF is not a signal at the libc level. It is just a successful read of 0 characters.
I assumed there had to be a handling of EOF implemented in the new pipe feature. Thanks for pointing me to it! This looks like a sound solution to my problem. You can expect my patch by the end of the week :)
Cheers Sid
Hi Norman,
so, I ended up implementing a different approach. In my first mail describing my problem, I emphasized too much on the Terminal session. I clearly failed at writing concise requirements, without any unnecessary solutions attached.
To me, the Terminal session is best used when controlling your component in an interactive manner. The reason I initially chose it was that there was an easy way to attach `stdin` and `stdout` to a libc component.
Now, for my use-case, interactiveness is not required. What I want is an easy way to send data from one component to a libc component via `stdin` and read from the libc components `stdout`.
This problem reminded me of how named pipes on unix. So, I implemented a `named_pipe` plugin for `vfs` [1], which solves my problem perfectly.
Any feedback appreciated.
[1] https://github.com/genodelabs/genode/issues/3583
Cheers Sid