Sziasztok!
ruby --version
ruby 1.8.7 (2010-08-16 patchlevel 302) [x86_64-linux] (Gentoo)
Lenne egy olyan (lehet triviális, nem látom fától az erdőt) problémám, hogy a következő kódsor miért terheli 100%-ban cpu -t:
require 'socket'
server = TCPServer.open(9010)
loop {
Thread.start(server.accept_nonblock) do |client|
client.puts 'Haliho!'
client.close
end
}
Amikor megszakítom a folyamatot, akkor a 'Thread.start(server.accept_nonblock) do |client|' sornál várakozik.
A TCP connectek szépen mennek, nincs baj. Próbáltam már szimplán server.accept -el, szálasítás nélkül, loop {} nélkül is, sikertelenül. Tanácstalan vagyok.
Köszönöm!
Megoldás:
A bug nem a Ruby-ban van, hanem az én programomban bújkált.
Ha fenti kódot ha ki akarod próbálni akkor server.accept_nonblock _helyett_ server.accept -et használj, azzal futni fog.
- 1354 megtekintés
Hozzászólások
nonblock
ezert. igy nem is fog menni. csak magas load-dal. a nonblock rossz, ertem? ;)
server.accept
igy kell csinalni. igen, ez meg nem egyszeru". multiplexeles is kell ha nem akarsz szalasitani, valahogy, amit a nyelv tamogat. nem ismerem a ruby-t, de a c-beli select()-nek megfelelo" helyen keresgelj. illetve csinalhatsz me'g a sigio/sigpoll-nak megfelelo "kivetelezo" variaciot is, az is egy kellemes lehetoseg, csak az (szvsz) megnyugvenyelosebb.
- A hozzászóláshoz be kell jelentkezni
Rendben, a nonblock rossz :)
Az igazság az, hogy nincsennek túl mély C ismereteim, de igyekszek utánaolvasni a dolgoknak, köszönöm.
- A hozzászóláshoz be kell jelentkezni
egyebkent nekem igy siman _nonblock nelkul mukodokepesnek tunik a dolog. persze a multitaszk-reszet (tobb kliens) ennel jobban teszteld:
require 'socket'
server = TCPServer.open(9010)
loop {
Thread.start(server.accept) do |client|
client.puts 'Haliho!'
sleep(3)
client.puts 'qqriq'
client.close
end
}
nalam (deb, lenny, default ruby: ruby 1.8.7 (2008-08-11 patchlevel 72) [x86_64-linux]) ez a fenti tokeletesen megy, 2 kliensre is es nem terheli a procit egyatalan.
a.
- A hozzászóláshoz be kell jelentkezni
hm, mondjuk az eredeti valtozatot is kiprobaltam amit irtal, es az nem megy:
$ ruby x.ruby
x.ruby:5:in `accept_nonblock': Resource temporarily unavailable - accept(2) (Errno::EAGAIN)
from x.ruby:5
from x.ruby:4:in `loop'
from x.ruby:4
(egyebkent a c-vel eleg szoros a kapcsolat, innen latszik, mert egy nonblock socket az accept()-re ugyanugy errno==eagain-nal ter vissza /azaz hibaval!/, mint c-ben, szoval ezek a ruby-fuggvenyek gyk 1:1 megfeleltetesek lehetnek a libc-s valtozatra /gyk berkeley socket api-ra/, es nem a nyelv szerves resze)
- A hozzászóláshoz be kell jelentkezni
Megadtad a kulcsot a megoldáshoz :)
Az eredeti programrészt átmásoltam egy üres állományba, majd onnan futtatva, nekem se terhelt semmit és a fenti nonblock-os hibát dobta. Az eredeti helyén azért "működött" mert ha a 9010-es port hibát dob, akkor megpróbálja 9011-esen a szervert, de míg a 9010-es valamiért nonblock -os, a 9011 már nem az (én se értem miért, szerintem sima figyelmetlenség), mindezt a teszt kliensben is csendben lekezelve én pedig nem is figyeltem a portokra, csak arra hogy tekeri a cpu-t és hogy megy.
Aztán elkezdtem a programomat sorról - sorra átnézni és kiderült hogy az egész herce-hurca egy másik állományban bújkáló, új szálon induló programrész miatt volt, ahol sikerült egy végtelen ciklust alkotni, így hiába kommentelgettem ki közel mindent, nem ott volt a hiba, ahol vártam.
Ha nem írod, hogy neked működik szerintem beláthatatlan ideig szívtam volna a dologgal. Jó kis lecke volt.
Szóval, köszönöm! :)
- A hozzászóláshoz be kell jelentkezni
Es nem is tevedsz nagyot. A socket kezeles korul, ha jol tudom, nagyon minimalis a nativ ruby kod, rengeteg kernelhivas van. Ha jol emlexem, az az osztaly tisztan C
--
Ki oda vagyik, hol szall a galamb, elszalasztja a kincset itt alant.
- A hozzászóláshoz be kell jelentkezni