FIFO

Started by newdep, March 15, 2004, 08:13:13 AM

Previous topic - Next topic

newdep

Hello Lutz,



Have you thought about supporting [FIFO] for newlisp?

(mknod -p / mkfifo )



Regards,

Norman.
-- (define? (Cornflakes))

Lutz

#1
there is a 'pipe' if you are running on LINUX or other UNIX, but you probably mean named pipes. This is what I just tried on LINUX and it works great:





- in first shell:



newLISP v7.5.10 Copyright (c) 2004 Lutz Mueller. All rights reserved.



> (import "/lib/libc.so.6" "mkfifo")

mkfifo <402E1DA0>

> (mkfifo "/home/lutz/fifotest" 0777)

0

> (open "/home/lutz/fifotest" "w")



- newLISP will no hang in the 'open' waiting for some other process to open 'fifotest' for "read"

- in second shell:

newLISP v7.5.10 Copyright (c) 2004 Lutz Mueller. All rights reserved.



> (open "/home/lutz/fifotest" "r")

3

>

- now newLISP in the first shell will unblock and also return the file handle '3'

- in the firsy shell:

> (write-buffer 3 "hello world")

11

>



- and in the second shell:



>(read-buffer 3 'buff 20)

11

> buff

"hello world"



The first to open the pipe will always hang wating for the other process to open the pipe. I could supply some kind of optional non-blocking in 'open' in the next version to avoid this. But if you can work around the blocking, it is usable now.



Lutz

newdep

#2
Hello Lutz,



Yes thats what i tested and worked fine, the blocking is no problem for me there

in the UNix scripting its the same case actualy...



Thanks for the reply..



Norman.
-- (define? (Cornflakes))

Lutz

#3
or course you also can simply do:



(exec "mkfifo /tmp/fifotest")



the next version will also have a (open "myfifo" "pipe") mode which opens non-blocking for reading.



Lutz

newdep

#4
Thanks ;-) great enhancement !



Norman.
-- (define? (Cornflakes))

pjot

#5
Hi Lutz,



I tried this new "pipe" feature with newLISP 7.5.12. This is my communication function:



(define (gtk str)

(set 'handle (open "gtk" "write"))

(write-buffer handle str)

(close handle)

(set 'handle (open "gtk" "pipe"))

(read-buffer handle 'tmp 20)

(close handle)

tmp)



But it appears that when the named pipe "gtk" already exists, newLISP will delete the file, after which I receive the error "open: No such file or directory". How is this possible?



An open with 'read' or 'write' works perfectly OK.



Peter.

Lutz

#6
I looks like you program is just creating/opening a normal file and writing reading to/from it. How did you create the named pipe? Did you do a:



/home/johndoe/> mkfifo myfifo



If you would have done this wour program would have hung after:



(set 'handle (open "gtk" "write"))



and would not have returned until in a different process of newLISP a



(set 'handle (open "gtk" "read"))



;;or



(set 'handle (open "gtk" "pipe"))



is performed.



You would use the "pipe" option only if the process is opening the pipe first and for reading.





Try again and do the following:



at the operating system level (must be LINUX/UNIX):



/home/pjot/> mkfifo fifotest



Now in the first newLISP process:



> (open "fifotest" "p")     ;; opened for reading, will not block because of "p"

3



Now in the second newLISP process:



> (open "fifotest" "w")

3

> (write-buffer 3 "hello world")

11            



Now in the first newLISP process:



> (read-buffer 3 'buff 20)

11

> buff

"hello world"



After you are done close the pipe in both processes. I think you where just using a file but not  a pipe and two newLISP processes.



Lutz

pjot

#7
All right, I'll put the complete program here. Actually, my GTK-server creates the named pipe and it does so correctly  (the 'p' bit is set, and other langauges can read and write through this file). In C in my GTK-server I am using the command "mkfifo(argv[2], S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP | S_IWOTH | S_IROTH)" for that.



Now, this is my newLISP program (just a plain rewrite of the existing one):



#!/usr/bin/newlisp

;;

;; Demonstration on how to use the GTK-server with NEWLISP by FIFO.

;; Tested with newLISP 7.5.12 on Slackware Linux 9.1.

;;

;; March 16, 2004 by Peter van Eerten.

;;

;;------------------------------------------------



;; Define communication function

(define (gtk str)

(set 'handle (open "gtk" "write"))

(write-buffer handle str)

(close handle)

(set 'handle (open "gtk" "read"))

(read-buffer handle 'tmp 20)

(close handle)

tmp)



;; Start the gtk-server

(process "gtk-server fifo gtk")



;; Wait a little so the server can initialize

(sleep 1000)



;; Design the GUI

(gtk "gtk_init(NULL, NULL)")

(set 'win (gtk "gtk_window_new(0)"))

(gtk (append "gtk_window_set_title (" win ", This is a title)"))

(gtk (append "gtk_window_set_default_size (" win ", 100, 100)"))

(gtk (append "gtk_window_set_position (" win ", 1 )"))

(set 'table (gtk "gtk_table_new(30, 30, 1 )"))

(gtk (append "gtk_container_add (" win "," table ")"))

(set 'button1 (gtk "gtk_button_new_with_label (Exit)"))

(gtk (append "gtk_table_attach_defaults(" table ", " button1 ", 17, 28, 20, 25)"))

(set 'button2 (gtk "gtk_button_new_with_label (Print text)"))

(gtk (append "gtk_table_attach_defaults (" table ", " button2 ", 2, 13, 20, 25)"))

(set 'entry (gtk "gtk_entry_new()"))

(gtk (append "gtk_table_attach_defaults (" table ", " entry ", 2, 28, 5, 15)"))

(gtk (append "gtk_widget_show_all(" win ")"))



(set 'event1 0)

(set 'event2 0)



;; This is the mainloop

(while (and (= (integer event1) 0) (= (integer event2) 0))

   (gtk "gtk_main_iteration()")

   (set 'tmp (gtk (append "gtk_server_callback(" button2 ")")))

   (if (> (integer tmp) 0)

      (begin

         (set 'tmp (gtk (append "gtk_entry_get_text(" entry ")")))

         (println (append "This is the contents: " tmp))))

   (set 'event1 (gtk (append "gtk_server_callback(" button1 ")")))

   (set 'event2 (gtk (append "gtk_server_callback(" win ")")))

)



;; Exit GTK explicitly

(gtk "gtk_exit(0)")



;; Delete NAMED PIPE

(delete-file "gtk")



;; Exit newLISP

(exit)



==================



Now, this program runs fine. When I change the "read" into "pipe" however, the problem occurs.



It seems to me that your "pipe" is overwriting an existing file?

Lutz

#8
thanks for the detail. This is what I tried:



In the first newLISP peocess I load the 'gtk' function and run it:



(gtk "hello world")



In the second newLISP:



> (open "gtk" "read")

3

> (read-buffer 3 'buff 20)

11

> buff

"hello world"

> (close 3)

true

> (open "gtk" "write")

3

> (write-buffer 3 "hi there")

8

> (close 3)



An then in the first I see:

"hi there"



So things are working fine. Now if I change "read" in the gtk function to "pipe", the second newLISP returns an empty string and 0 charcters read:



> (open "gtk" "read")

3

> (read-buffer 3 'buff 20)

0

> buff

""

>

and the first newLISP where gtk was called returns its own message:



> (gtk "hello there")

"hello there"

>



Which seems logical, becuase the write in gtk on the first newLISP unblocks as soon as the second newLISP does (open "gtk" "read"), now the first newLISP opens the pipe unblocked for reading and immedeately reads its own stuff instead of staying hung in the open waiting for the second newLISP to close and open again for writing back to the first newLISP.



To make a long story short: the pipe in my case is still there and not overwitten. I guess that in this scenario opening the pipe reading with "read" is the better thing to do.



Lutz

pjot

#9
Hi Lutz,



So I have tested my program with some additional tricks. The problem is that the write and read in my communication function are executed too fast right after eachother.



So, if I write something to the pipe, after that the non-blocking read will read immediately my own contents. Therefore the pipe always appears to be empty to the gtk-server. The script will be executed and reach the end where the PIPE file is deleted.



Therefore a SLEEP between the 'write' and 'read' probably solves the issue. I will test this tonight.



Thanks a lot for your info!



Peter.

Lutz

#10
Perhaps I should not call this mode "pipe", but rather supply an additional option "non-block" or "n", which can be put after the "read" or "write" option.



Calling it "pipe" makes the user think that it is mandatory for pipes, which is not true, it's just an additional option which may or may not be useful in a pipe scenario. There is an interesting discussion about this in "Linux Programming" by Matthew & Stones.



Lutz