From: "Ara.T.Howard" Date: 2004-03-27T03:14:27+09:00 Subject: Re: non blocking read and thread On Sat, 27 Mar 2004, Tanaka Akira wrote: > In article <000001c4134c$0cbe5920$0300a8c0@boulba>, > "yannick" writes: > > > You are right, after further tests; it looks like a thread scheduling > > problem, it could perhaps be solved by making the thread critical, but > > then it only return the EAGAIN error. Well, it seems I'm stock here, > > better find another way around :-) > > I recommend sysread instead of IO#read with nonblocking mode. can you please elaborate on this? why exactly? > However, your first script is interesting because it transit > multithread to singlethread after sock.read(100) is started. > > When there are two or more threads, Ruby calls select(2) before each > IO operation for thread scheduling. But Ruby doesn't call select(2) > when there is only one thread. > > Your first script invokes following system calls. > > % strace -e read,write,select ruby tst1 > .. > select(0, [], [], [], {0, 0}) = 0 (Timeout) > select(6, [5], [], [], {1, 999368}) = 0 (Timeout) > select(6, [5], [], [], {0, 3115}) = 0 (Timeout) > select(6, [5], [], [], {0, 0}) = 0 (Timeout) > select(9, [5], [7], [], NULL) = 2 (in [5], out [7]) > write(1, "try to read it...\n", 18) = 18 > (*1) select(9, [8], [], [], {0, 0}) = 0 (Timeout) > write(1, "send a message\n", 15) = 15 > select(9, [8], [7], [], NULL) = 1 (out [7]) > write(7, "message", 7) = 7 > select(9, [8], [7], [], NULL) = 2 (in [8], out [7]) > select(9, [8], [], [], {0, 0}) = 1 (in [8], left {0, 0}) > write(7, "\n", 1) = 1 > (*2) read(8, "message\n", 1024) = 8 > (*3) read(8, 0x4001a000, 1024) = -1 EAGAIN (Resource temporarily unavailable) > write(1, "done !\n", 7) = 7 > > System calls corresponding to sock.read(100) is (*1), (*2) and (*3) > > (*1) Check sock is readable or not. Since it is not readable yet, > it blocks and switch to other thread. > (*2) Read 8bytes from sock: "message\n". > (*3) Occur EAGAIN. It terminates sock.read(100). > > What interesting is that select is not called before (*3). > If select is called at (*3), it blocks forever. > This means that there are no thread other than the main thread. > Actually the client thread is finished before (*2). > > So sock.read(100) blocks at first(*1) by select because multithread. > But it doesn't block at last(*3) because singlethread. > > I think this behavior is very confusing. if it is confusing to you, we are all doomed! your explanations are really insightful and i for one _really_ appreciate you taking to time to enlighten maybe dave could have you write the new pickaxe thread section! ;-) -a -- =============================================================================== | EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov | PHONE :: 303.497.6469 | ADDRESS :: E/GC2 325 Broadway, Boulder, CO 80305-3328 | URL :: http://www.ngdc.noaa.gov/stp/ | TRY :: for l in ruby perl;do $l -e "print \"\x3a\x2d\x29\x0a\"";done ===============================================================================