| [ Return to Bugs & Features | SVN ⇄ GIT ]
STR #2107
Application: | FLTK Library |
Status: | 2 - Closed w/o Resolution |
Priority: | 1 - Request for Enhancement, e.g. asking for a feature |
Scope: | 2 - Specific to an operating system |
Subsystem: | OS support |
Summary: | WIN32: Fl::add_fd does not work well with anonymous pipes |
Version: | 1.4-feature |
Created By: | manolo |
Assigned To: | manolo |
Fix Version: | 1.3-current |
Update Notification: | |
Trouble Report Files:
Trouble Report Comments:
|
#1 | manolo 22:48 Dec 19, 2008 |
| I find that, under WIN32, Fl::add_fd works only superficially when the monitored file descriptor is an anonymous pipe. I don't know if you know that already perfectly, but the documentation is silent on this subject. (Under Mac OS X and X11, add_fd works beautifully on pipes.) If data comes steadily from the pipe, all is well, but if the pipe remains empty for a long time, this happens: Fl::wait() calls select select returns that the fd is to be read (note that select is sold for sockets on WIN32, not for pipes) Fl::wait() calls the fd's callback which calls read(fd,...) which blocks until some data arrives in the pipe.
The result is that the GUI, blocked in Fl::wait(), is frozen.
So I use the following code, that does not block when the pipe is empty, to monitor pipe incoming data: DWORD avail = 0; //is there data in pipe ? PeekNamedPipe(_get_osf_handle(fd), NULL,0,NULL, &avail, NULL); if(avail > 0) read(fd,...) //read data from pipe
Another call that correctly detects whether there is data to be read in the pipe is: if( WaitForSingleObject(_get_osf_handle(fd), 0) == WAIT_OBJECT_0) but it is unclear for me how to detect pipe closure by its writer, so all of this does not really solve how to write under WIN32 Fl::wait() generically for any fd as it is under Unix. | |
|
#2 | greg.ercolano 00:12 Dec 20, 2008 |
| Is the data you're transmitting ASCII and delimited by CRLFs? If so, make sure the child is flushing its output regularly enough. If you're sending binary data, be sure both ends of the pipe agree on the blocking size.
Try to include a *small* example program here showing the FLTK app and the child, and how the two are interacting.
FWIW, I decided quickly Microsoft did not do a great job implementing the unixy functions for pipes (eg. select()/read()/etc. for pipes), however, I found their WIN32 API calls like CreatePipe() + CreateProcess() (and related calls) are fairly reliable. To use them effectively, I found it involved making a child thread to handle reading the pipe, so if it blocked, FLTK was unaffected. When data was fully ready, the child would dump it in a buffer common to the two threads, and set a flag. The FLTK parent thread would use an FLTK timer to keep an eye on the flag, and when set, would lock the data and read it, then clear the flag. This way there was no chance the FLTK thread would hang up waiting for data; the child thread would deal with it, and could hang as much as it liked. | |
|
#3 | greg.ercolano 00:23 Dec 20, 2008 |
| > I find that, under WIN32, Fl::add_fd works only superficially > when the monitored file descriptor is an anonymous pipe. I don't > know if you know that already perfectly, but the documentation > is silent on this subject.
BTW, the docs on Fl::add_fd() seem to be fairly distinct about this: http://fltk.org/documentation.php/doc-1.1/Fl.html#Fl.add_fd
Quoting the docs: "Under UNIX any file descriptor can be monitored (files, devices, pipes, sockets, etc.) **Due to limitations in Microsoft Windows, WIN32 applications can only monitor sockets.**"
So I read that to mean what you're doing is specifically not supported.
I think this limitation has to do with how Microsoft implemented select() for BSD network sockets only, and not an across the board solution for all the things the win32 select() function supports, such as pipes.. named or otherwise.
I think you're right to follow your instincts to go with the WIN32 API calls under windows. My reply above about how to use a child thread to read the pipe into a buffer and an FLTK timer to lock/read the buffer is a reliable method. | |
|
#4 | manolo 02:29 Dec 20, 2008 |
| Many thanks for the fast and exhaustive replies. I am sorry not to have seen the explicit limitation of Fl::add_fd to sockets under WIN32 in the documentation. So I understand pipe monitoring is not supported by FLTK under WIN32.
Just in case, I attach my solution to my problem: run an external program in a pseudoterminal window built by FLTK to receive the program's output, with the possibility to interrupt this program. It is essentially the same as fluid's Fl_Process. The interface is function run_external_prog_in_pseudoterm, and its works nicely on all 3 windowing systems. | |
|
#5 | matt 09:40 Dec 20, 2008 |
| add_fd only works with sockets on MSWindows as mentioned in the docs. The soluton could be a Fl_Pipe class fro cross-platform availibility. | |
|
#6 | manolo 23:33 Mar 10, 2015 |
| The doc explicitly states that Fl::add_fd does not work with anonymous pipes under MSWindows. | |
[ Return to Bugs & Features ]
|
| |