From: Gustavo S. B. <bar...@pr...> - 2008-04-15 16:16:13
|
On Tue, Apr 15, 2008 at 1:28 AM, The Rasterman Carsten Haitzler <ra...@ra...> wrote: > On Sun, 13 Apr 2008 13:35:58 -0300 "Gustavo Sverzut Barbieri" > <bar...@pr...> babbled: > > On Sat, Apr 12, 2008 at 2:37 AM, The Rasterman Carsten Haitzler > > <ra...@ra...> wrote: > > > no need to make it blocking :) look at ecore_con - hell look at emotion. > > > it's > > > > Well, I looked at emotion and damn, it's wrong! :-P > > > > Ok, it will work for most of the cases where you are within the buffer > > size, but then it would also not block if you're in the same situation > > and have not set the non-blocking flag. > > > > The problem is at the border condition: full buffer: > > - blocking would block the call and make the sender process (in this > > case, the thread) to block a while... IMO this is not so bad, as the > > main process is not being capable of reading it at all. > > - non-blocking would write partial and stay looping to write the > > remaining bytes... so blocking the same way, or it would do a partial > > write if you don't loop. Also, on the read side, depending on the > > implementation it would either loop (so blocking) waiting for data or > > do partial reads (as it might do with Emotion), these partial reads > > are the damn bug-causing I'm talking about. > > > > read() and write() does not do all the work for us because these are > > really low level functions enabling us to do such a looping solution > > (that blocks in any way) or queueing the data elsewhere (todo-buffers) > > and doing something else if the read/write fails... but doing these > > todo-buffers is really a PITA, I never see nobody using them, maybe > > these are used in some high-performance servers that can keep > > todo-buffers for each socket and try to dispatch other sockets if some > > are blocked. > > > > > > Just read emotion code and consider: > > - Thread 1: write 3xmessage-size bytes (consider message-size being > > 2 bytes: [AA|BB|CC]) > > where? it writes void * sized messages. the vo_out plugin writes only 1 void * > msg, the slave writes 2 * void *, the event thread writes 2 * void *. no 3x > there? it was just to make the example simpler, the simplest case. > > - Thread 2: read message-size bytes [AA], then read 1 byte [B]... > > it's not of message-size bytes, then discard (!!!) and try to read > > message-size bytes again, which you can do because you still have 3 > > bytes there, so you end with [BC], then you process this wrong pointer > > and then read message-size again, being unable because just [C] is > > there. > > hmm in practice this won't happen. thread 1 has written a full message into the > fd - it's all available, or should be. :) as kernel buffers are 64k or 148k - > but are always a page size multiple in reality, you will always have a whole > number of messages in the buffer :) Ok, ok, but taking care of this will not increase complexity, but would make code more correct. > > I don't even want to read ecore_con! If it resemble emotion then it's > > wrong and it might incur in security risk for all code using it... The > > risky is not that important since you don't handle pointers to a > > process to another, just between threads, and nobody would replace a > > thread... :-P > > ecore_con knows nothing of message sizes. it just reads as many bytes as it can > and puts them into a buffer together then hands it off to the rest of the app > as an event. ic, then good... this is the case where it all works well: keep a buffer with partial reads, thatś what we don't have in this thread-sync case. > > What also makes me wonder: why not make this kind of thing available > > in ecore? Just handle read/write file descriptors to a function to > > have these configured (maybe also set the buffer size based on message > > size) and provide ecore_read() and ecore_write() with these loops all > > handled? This is way better than spreading these weird loops all over > > the code, many can be just wrong and will spread bugs :-/ > > that is what the talk of ecore_pipe was about. it would set up these pipes, fd > handlers etc. and handle putting messages on the pipe queue and gettting them > off and presenting them as events - much like ecore_con. fine, so we agree :-) > > Ok, your example fits into the buffer size exactly, but we shouldn't > > trust this to be always true. Also, as I tried to show, the blocking > > code would just do the same thing and make the error-handling easier. > > i know it does :) that's why i did it :) but yes - block on WRITE would be > good. blocking read is what i was thinking - u don't want to block :) in our case it won't matter! According to you, we WILL get the required data (multiple of page size, enough buffer size). But if we don't, then we do a busy-waiting looping on read(2) call to get the data... that's BAD. So we also block on READ, or we don't have any problem (from what you consider) or we block and don't suck 100% CPU (from what I said). For simplicity, I would just process one message per callback from ecore_fd_main... but we can also use a poll/select inside this function and do what you want, without the need to fcntl to NONBLOCKING. -- Gustavo Sverzut Barbieri http://profusion.mobi Embedded Systems -------------------------------------- MSN: bar...@gm... Skype: gsbarbieri Mobile: +55 (81) 9927 0010 |