staatsvr@asdcds.cds.wpafb.af.mil ( Vern Staats;;) (11/10/89)
In article <8911081827.AA12003@turnpike.sun.com> argv@SUN.COM (Dan Heller) writes: >If you've been reading comp.windows.x, you'll see a very short-lived >discussion about how XtAddInput is broken --I recommend *strongly* >that you avoid using it till it's fixed. This includes R4; I checked >the source. The problem is that your routine gets called continuously >rather than, as the spec says, "when there is data to be read." > I have had some success using XtAppAddInput on our Ultrix 3.1 Vaxen. In particular, I am sending commands to the X11 application over a named pipe (fifo), which is opened with the O_NDELAY flag to return errors rather than blocking on reads. I was able to prevent the input callback routine from being triggered continuously by opening the pipe for both reading and writing in the X11 program, even though the program never writes to the pipe. The man page for read(2) says that with O_NDELAY set, read will return 0 to indicate end-of-file rather than the -1 error return if no process has the pipe open for writing. My guess is that the select call in WaitForSomething() is also affected by whether a process has the pipe open for writing or not. Even after opening a dummy_write file descriptor I was getting two calls to the input callback routine for every actual input I sent it. Putting calls to XtRemoveInput() and XtAddInput() in the input callback routine (to destroy and then re-install itself) prevents the second call, although I suspect it may be more efficient just to live with it and do a quick return in the callback if ioctl says the pipe is empty. ---- /// INET: staatsvr@asd.wpafb.af.mil Vern Staats (513) 255-2714 \\\/// UUCP: -Maybe- nap1!asd!staatsvr ASD/SCED WPAFB OH 45433 \XX/ Boolean orthogonal(char *my_opinions, char *employer_opinions) {return(TRUE);}
bjaspan@athena.mit.edu (Barr3y Jaspan) (11/10/89)
I've seen random discussion about the use of XtAddInput() and about how it supposedly does not work. It *does* work, and I will attempt to clear up the confusion. Anyone who is familiar with UNIX realizes that the intrinsics use select() to detect X and other events, and that XtAddInput() merely adds filedescriptors to the parameters passed to select. The man page for select() says that it returns when there a file descriptor is "ready for reading, ready for writing, ..." The confusion, I think, is in "ready for writing." That means that the fd is in a state such that data CAN be written to it, not that data actually has been written to it. Specifically, stdout is ALWAYS "ready for writing" (unless it has been messed with) and so *IF YOU DO AN XtAddInput ON FD 1, IT WILL TO CALL THE FUNCTION CONSTANTLY* and that is the correct behavior. For input events, XtAddInput also does the right thing: it calls the function whenever there is data waiting to be read. For example, if you do XtAddInput() on fd 0 with XtInputReadMask, the callback will be called when the user has typed a line (or a character in cbreak mode). The function IS NOT called constantly. As proof of my argument, I present the following source code and execution output. --- snip snip --- #include <stdio.h> #include <X11/Intrinsic.h> #include <X11/StringDefs.h> #include <X11/Label.h> void input(); main(argc, argv) int argc; char **argv; { Widget top; top = XtInitialize("Hello", "World", NULL, 0, &argc, argv); (void) XtCreateManagedWidget("label", labelWidgetClass, top, NULL, 0); XtAddInput(0, XtInputReadMask, input, NULL); XtRealizeWidget(top); XtMainLoop(); } void input(client_data, source, input_id) caddr_t client_data; int *source; XtInputId *input_id; { char buf[BUFSIZ]; printf("Input received on fd %d.\n", *source); scanf("%s", buf); printf("\"%s\"\n", buf); } --- snip snip --- ~% cc -I/mit/x11/include -L/mit/x11/vaxlib input-example.c -lXaw -lXmu -lXt -lX11 ~% a.out testing Input received on fd 0. "testing" Hi there!! Input received on fd 0. "Hi" ^C~% Barr3y Jaspan, MIT-Project Athena bjaspan@athena.mit.edu Barry Jaspan, MIT-Project Athena bjaspan@athena.mit.edu
argv%turnpike@Sun.COM (Dan Heller) (11/10/89)
In article <15783@bloom-beacon.MIT.EDU> bjaspan@athena.mit.edu (Barr3y Jaspan) writes: > I've seen random discussion about the use of XtAddInput() and about > how it supposedly does not work. It *does* work, and I will attempt > to clear up the confusion. Ironic -- I was just about to post a followup to my previous message but you beat me to it. Well, you said just about what I was going to say. I was mistaken about a couple of things which caused the confusion. Agreed -- this function _does_ work. However, there is a case where it's difficult to tell :-) I think someone pointed out the problem in another message recently, but didn't emphasize it strongly enough and I think it should be because it also addresses the confusion I mentioned above. I originally said that XtAddInput didn't work because it called your routine constantly whether there was input there to be read or not. This isn't true _until it reaches EOF_. Because the file descriptor has been modified (FNDELAY I believe), when you're reading on a *file* and you get to the end of the file, read() no longer returns -1, it returns 0 and your function is called. It's hard to tell what the right thing to do is -- if you want to monitor a file (ala tail -f), then you're going to have to put up with your function getting called all the time and your having to do ioctl(fd, FIONREAD, &n) to find out if there is anything actually there to be read. The problem here is that your cpu-usage goes thru the roof. This is not a problem on pipes and other types of file descriptors. dan
gjc@mga.COM (George J. Carrette) (11/11/89)
XtAddInput works great in VMS, exactly as one would expect, with no funny glitches. The only problem is that it limits you directly to a QIO level interface, (or an AST EVENT/FLAG one if you are clever). Getting access to the usual record-management-services level is a bit tricky. But being able to use the VAX-C run-time-library with its fopen/open and getc/puts read/write is hopeless (undocumented internals structure). So the portability aspects of the thing are hopeless, unless you punt the DIGITAL provided C-runtime-library for your own. -gjc
mvh@cfa250.harvard.edu (Mike VanHilst) (11/12/89)
In article <15783@bloom-beacon.MIT.EDU> bjaspan@athena.mit.edu (Barr3y Jaspan) writes: > I've seen random discussion about the use of XtAddInput() and about > how it supposedly does not work. It *does* work, and I will attempt > to clear up the confusion. and procedes to explain how select() works on stdin and stdout. While in article <294@nap1.cds.wpafb.af.mil> staatsvr@asdcds.cds.wpafb.af.mil ( Vern Staats;;) writes: > I have had some success using XtAppAddInput on our Ultrix 3.1 Vaxen. >In particular, I am sending commands to the X11 application over a >named pipe (fifo), which is opened with the O_NDELAY flag to return >errors rather than blocking on reads. I was able to prevent the input >callback routine from being triggered continuously by opening the pipe >for both reading and writing in the X11 program, even though the program >never writes to the pipe. I too, am using name pipes as a convenient mechanism for remote control of my application while having a functioning user interface. My experience has been that problems such as those discussed above, have much to do with the behavior of the pipe under different conditions, on different operating systems, and little to do with how select() is called. It seems that the behavior is not precisely defined for BSD4.3 and may differ among vendors. To wit: under SunOS 3.5 and 4.0.3, if a pipe is opened to read and set to block (I open it with O_NDELAY, so as not to block on the open(), and then use fcntl() without the O_NDELAY, to set blocking), select() only returns with its flag when something is in fact available to be read (I never find a read of 0 in response to being called). Under Ultrix 3.1, the pipe cannot block if the pipe is not currently opened for writing by some process. It always returns from select(), and fcntl() cannot change this condition. (This condition, BTW, is not consistent as, on occasion, it functions as on the Sun). Under Ultrix 2.0, it could be set to block by fcntl(), but reverted to non-blocking when the writer opened and then closed its end. The method that seems to work in all cases is to open the pipe on another descriptor for writing (as a dummy), and not close that connection until closing the connection for reading. There is a catch, in that opening to write may fail if there is no reader, so the sequence, open to read non-blocking, open the dummy to write, fcntl() the reader to block, must be followed. I ifdef this out for the Sun, due to a desire to preserve its fewer available descriptors, as mentioned in another discussion. I have not tried opening the pipe read/write as Vern suggests. My suggestion for any new port, is always to test with tiny programs just to open for writing and reading with select() to test that OS's behavior. Now, if somebody could explain this procedure under SysV (i.e. Apollo), I would be much obliged. ------ Mike VanHilst mvh@cfa.harvard.edu Smithsonian Astrophysical Observatory (617)495-7260 60 Garden Street, Cambridge, MA 02138