This is the new home of the egghelp.org community forum.
All data has been migrated (including user logins/passwords) to a new phpBB version.


For more information, see this announcement post. Click the X in the top right-corner of this box to dismiss this message.

tclsh called via open

Help for those learning Tcl or writing their own scripts.
Post Reply
User avatar
De Kus
Revered One
Posts: 1361
Joined: Sun Dec 15, 2002 11:41 am
Location: Germany

tclsh called via open

Post by De Kus »

I am currently triing to get the http request speed up in my weather script (refer script support forum for a copy) which uses the http -command thing to get a asyncronous conenction.
Now the problem is, it takes about 20-40sec to get the data which are downloaded in 1sec in syncronous mode. Now you might wonder why I dont use syncronous then... well the reasons should be obvious. I dont want to get the bot stuck just because the site is not avaible or really slow.

My idea was:

Code: Select all

		set fd [open "|tclsh8.4" r+]
		puts $fd "package require http 2.4"
		if {[info exists wetter(useragent)]} {
			puts $fd "::http::config -useragent $wetter(useragent)"
		}
		puts $fd "puts -nonewline stdout \[array get \[::http::geturl $query -headers {Host www.wetter.com Connection close}\]\]"
		fconfigure $fd -blocking 0
		putlog "Log: [read $fd]"
		fileevent $fd readable [list getwetter:cb $fd]
But the problem is... nothing will be read. no command prompt, not an empty string, just nothing (calling read in syncronous mode will stuck and in asycronous will return empty string in a seperate tclsh on console. fileevent will never trigger of course and tclsh idle forever unless I kill the tclsh process which also triggers the filevent script then). Any idea how to use tclsh within tcl? The manual didnt give me any hints. Its only takling about .tclshrcs and tcl_prompt1 which both dont really matter :D.

PS: Yes, I thought about using lynx, but a) it doesnt return all infos like the http state var does b) lynx is not installed on every shell :D (wget might be hard to capture when its finished and creates unncessary hard disc usage)

simple example:

Code: Select all

~/eggi$ tclsh
% open |tclsh r+
file5

% puts file5 "puts stdout muh"
% read file5
gets stucked here... (strg+c to abort)

PPS: oh yeah, my first idea was using -blocksize 65532 (file is around 60kb) which made it about twice as fast, but ~15sec is still much too slow.
De Kus
StarZ|De_Kus, De_Kus or DeKus on IRC
Copyright © 2005-2009 by De Kus - published under The MIT License
Love hurts, love strengthens...
User avatar
sKy
Op
Posts: 194
Joined: Thu Apr 14, 2005 5:58 pm
Location: Germany

Post by sKy »

I really don`t know why i can`t opening | commands in read and write mode at the same time (r+ a+ w+). So this won`t work for tclsh aswell too. No one could telle me.

Not long ago i`ve got the same problem. But I can offer you several workarrounds.

1)
Let an external application (maybe written in tcl) doing the connection stuff and give you bot some callback.

2)
Start a tclsh process, called "eval server". Load a "eval client" as .tcl into the eggdrop. The communication can we done via sockets. This is imho the more worse solution.

3)
Use this package. =)
http://mkextensions.sourceforge.net/mkThreads12.htm
The disadventage is, you have to recompile the eggdrop with tcl 8.4.12. The tcl version must be compiled with --enable-threads. You can read more about it in the manual. Just put the connection stuff in it`s own thread. Inside the thread you can use vwait and blocking connections; them won`t block your bot.
Another disadventage: tcl with enabled threading isn`t something you can require in public scripts. If you`re interested in this methode just tell me, i can give you good examples if you want.
socketapi | Code less, create more.
User avatar
De Kus
Revered One
Posts: 1361
Joined: Sun Dec 15, 2002 11:41 am
Location: Germany

Post by De Kus »

sKy wrote:1)
Let an external application (maybe written in tcl) doing the connection stuff and give you bot some callback.
Do you know if I can bind to custom signals from kill? refering to TCL-Commands.doc it seems its only sighup, sigterm, sigquit and sigill.

Ill try to use an extern script and forwarding the url via arguments to tclsh, then I only need to open as read only which should work.

Edit: no chance. I cannot get anything from 'puts stdout $string' of the extern script. Any idea which file descriptor I need to write to? stdout should be the right one, it works on interactive console.
When I write everything I get from read after fileevent readable triggers is an empty string...

Code: Select all

% puts stdout "I am the message\t1\t2\t3"; return 0
I am the message        1       2       3
0
Edit2: I added a function to fetch fileevent triggers and tried to wait until a \n ends the line, but it simply reads 0 bytes (I made a var which increases with string length of the read string).
De Kus
StarZ|De_Kus, De_Kus or DeKus on IRC
Copyright © 2005-2009 by De Kus - published under The MIT License
Love hurts, love strengthens...
User avatar
sKy
Op
Posts: 194
Joined: Thu Apr 14, 2005 5:58 pm
Location: Germany

Post by sKy »

I guess there is no way to execute tclsh with getting return values.

You can just write an application and start it. This application just idle until you are asking for something via sockets.

And i think there is no way to bind event based. At least no easy way on tcl level. Maybe create a file and the bot check every 5-10 seconds if the file exist or not. This would be the eayest way the get the callback.
socketapi | Code less, create more.
User avatar
De Kus
Revered One
Posts: 1361
Joined: Sun Dec 15, 2002 11:41 am
Location: Germany

Post by De Kus »

sKy wrote:I guess there is no way to execute tclsh with getting return values.

You can just write an application and start it. This application just idle until you are asking for something via sockets.

And i think there is no way to bind event based. At least no easy way on tcl level. Maybe create a file and the bot check every 5-10 seconds if the file exist or not. This would be the eayest way the get the callback.
If I have to check every 5sec for an existing file or run a second background process (its a diffrent to spawn in a temporal thread and a 'daemon'), I can stick to internal async http.
De Kus
StarZ|De_Kus, De_Kus or DeKus on IRC
Copyright © 2005-2009 by De Kus - published under The MIT License
Love hurts, love strengthens...
Post Reply