You can subscribe to this list here.
2004 |
Jan
(57) |
Feb
(71) |
Mar
(80) |
Apr
(40) |
May
(49) |
Jun
(20) |
Jul
(3) |
Aug
(9) |
Sep
(8) |
Oct
(2) |
Nov
|
Dec
(11) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2005 |
Jan
(10) |
Feb
(25) |
Mar
(24) |
Apr
(26) |
May
(71) |
Jun
(35) |
Jul
(5) |
Aug
(3) |
Sep
(18) |
Oct
(4) |
Nov
(5) |
Dec
(2) |
2006 |
Jan
(50) |
Feb
(12) |
Mar
(7) |
Apr
(24) |
May
(1) |
Jun
(17) |
Jul
(51) |
Aug
(38) |
Sep
(38) |
Oct
(33) |
Nov
(8) |
Dec
(13) |
2007 |
Jan
(44) |
Feb
(25) |
Mar
(21) |
Apr
(68) |
May
(52) |
Jun
(24) |
Jul
(17) |
Aug
(12) |
Sep
(4) |
Oct
(14) |
Nov
(1) |
Dec
(3) |
2008 |
Jan
(9) |
Feb
(1) |
Mar
|
Apr
(5) |
May
|
Jun
|
Jul
(1) |
Aug
(1) |
Sep
(5) |
Oct
(5) |
Nov
(1) |
Dec
|
2009 |
Jan
(4) |
Feb
|
Mar
(2) |
Apr
(1) |
May
(21) |
Jun
(5) |
Jul
|
Aug
|
Sep
(4) |
Oct
(1) |
Nov
|
Dec
|
2010 |
Jan
(15) |
Feb
(36) |
Mar
(1) |
Apr
|
May
|
Jun
(2) |
Jul
(3) |
Aug
|
Sep
(2) |
Oct
|
Nov
(1) |
Dec
(3) |
2011 |
Jan
(22) |
Feb
(2) |
Mar
(2) |
Apr
(1) |
May
(2) |
Jun
|
Jul
(25) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(4) |
2012 |
Jan
(14) |
Feb
(6) |
Mar
(20) |
Apr
(12) |
May
|
Jun
(1) |
Jul
|
Aug
|
Sep
(1) |
Oct
(2) |
Nov
(2) |
Dec
|
2013 |
Jan
|
Feb
(3) |
Mar
(2) |
Apr
(1) |
May
(9) |
Jun
|
Jul
|
Aug
(1) |
Sep
|
Oct
|
Nov
|
Dec
(1) |
2014 |
Jan
(1) |
Feb
(1) |
Mar
(3) |
Apr
(2) |
May
(1) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2015 |
Jan
|
Feb
|
Mar
(5) |
Apr
|
May
|
Jun
(11) |
Jul
(1) |
Aug
(3) |
Sep
|
Oct
|
Nov
(1) |
Dec
|
2016 |
Jan
(2) |
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2018 |
Jan
|
Feb
(1) |
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: Jar <ja...@pc...> - 2010-02-22 15:29:16
|
Hello, While testing this again with e220, I noticed that the e220 was broken. While the newer huawei 3G modems accept several at commands at one line like "ATE1;^CURC=0;^DSFLOWCLR" the e220 does not. If I use "ATE1 ^CURC=0;^DSFLOWCLR" instead (first semicolon replaced by space) both e220 and e160 worked. Could you or someone else who has some extra time to apply this patch? -- Best Regards, Jar |
From: Martin Z. <co...@mz...> - 2010-02-15 21:49:47
|
Hi Michael! > Looks fine. Maybe you want to add some kind of limiting? What happens if the silly user specifies a timeout of 0 (zero)? Oops, got me! Actually, a USB read that never terminates is my idea of punishing silly users... :) Fixed. Martin P.S.: Gute Besserung! -- www.mzuther.de www.radix-musik.de |
From: Michael R. <mi...@re...> - 2010-02-15 18:44:18
|
Hi Martin, > I don't argue with you, the picoLCD *is* brain damaged. But there is > good in it, as well. Without this brain damage, I wouldn't have had a > go at the timers... ;) Think pink, eh? ;-) >> I'd recommend a value of 5 msec, and make it a config option within >> the display section > > So be it, I've just committed. Looks fine. Maybe you want to add some kind of limiting? What happens if the silly user specifies a timeout of 0 (zero)? or even worse, -1? bye, Michael (fighting the flu) -- Michael Reinelt <mi...@re...> http://home.pages.at/reinelt GPG-Key 0xDF13BA50 ICQ #288386781 |
From: Jar <ja...@pc...> - 2010-02-15 08:46:50
|
Hello, While testing this again with e220, I noticed that the e220 was broken. While the newer huawei 3G modems accept several at commands at one line like "ATE1;^CURC=0;^DSFLOWCLR" the e220 does not. If I use "ATE1 ^CURC=0;^DSFLOWCLR" instead (first semicolon replaced by space) both e220 and e160 worked. Can you apply this patch? -- Best Regards, Jar |
From: Martin Z. <co...@mz...> - 2010-02-14 13:04:23
|
Hi Michael, I don't argue with you, the picoLCD *is* brain damaged. But there is good in it, as well. Without this brain damage, I wouldn't have had a go at the timers... ;) > I'd recommend a value of 5 msec, and make it a config option within the display section So be it, I've just committed. Thanks, Martin -- www.mzuther.de www.radix-musik.de |
From: Michael R. <mi...@re...> - 2010-02-14 02:53:25
|
Hi Martin, > I had written that polling the button states using LCD::GPI(1) > considerably slows down output on my picoLCD 256x64 and located the > problem in this function: > > static int drv_pLG_read(unsigned char *data, int size) > { > return usb_interrupt_read(lcd, USB_ENDPOINT_IN + 1, (char *) data, > size, 1000); > } > > On second thoughts, I have made the mistake to think that this function > times out *every* time. When a key is pressed, however, the function > exits directly and thus only times out when no data are present for > usb_interrupt_read(). Well, this means the picoLCD does not answer with something like "zero keys pressed", but just times out? Sounds *a little bit* braindamaged to me ;-) > My problem is that I don't know what time-out value should be used. I > have experimented a little: 1 ms is too low, while 2 ms work fine on my > desktop. On my embedded system, 3 ms are needed. But what about people > using the display with an old USB 1.0 port? I propose 5 ms or 10 ms -- > what do you think? I's recommend a value of 5 msec, and make it a config option within the display section HTH, Michael -- Michael Reinelt <mi...@re...> http://home.pages.at/reinelt GPG-Key 0xDF13BA50 ICQ #288386781 |
From: Michael R. <mi...@re...> - 2010-02-14 02:49:21
|
Hi Jaro, > I have sent this patch to Michael at some time ago, but maybe he is busy right now > and have had no time to merge this. > > So can someone who has merge rights to SVN to apply this patch? Done. Sorry for the delay, I'm really busy these days, and I overlooked your mail (it didn't match the lcd4linux filter) bye, Michael -- Michael Reinelt <mi...@re...> http://home.pages.at/reinelt GPG-Key 0xDF13BA50 ICQ #288386781 |
From: Martin Z. <co...@mz...> - 2010-02-13 23:25:48
|
Hello everybody, I had written that polling the button states using LCD::GPI(1) considerably slows down output on my picoLCD 256x64 and located the problem in this function: static int drv_pLG_read(unsigned char *data, int size) { return usb_interrupt_read(lcd, USB_ENDPOINT_IN + 1, (char *) data, size, 1000); } On second thoughts, I have made the mistake to think that this function times out *every* time. When a key is pressed, however, the function exits directly and thus only times out when no data are present for usb_interrupt_read(). This means that the time-out value is *much* too high. The driver usually waits a *full second* for key data before going on and doing (more important) things like updating the LCD. As this makes the display rather unresponsive, I think that the time-out value should be changed. My problem is that I don't know what time-out value should be used. I have experimented a little: 1 ms is too low, while 2 ms work fine on my desktop. On my embedded system, 3 ms are needed. But what about people using the display with an old USB 1.0 port? I propose 5 ms or 10 ms -- what do you think? Thanks, Martin -- www.mzuther.de www.radix-musik.de |
From: Jar <ja...@pc...> - 2010-02-13 20:35:04
|
Hello, I have sent this patch to Michael at some time ago, but maybe he is busy right now and have had no time to merge this. So can someone who has merge rights to SVN to apply this patch? -- Best Regards, Jar |
From: Mattia Jona-L. <mat...@gm...> - 2010-02-12 11:44:55
|
Hi! I was having a look at the cfg_get routine and I found a segmentation fault error. char *cfg_get(const char *section, const char *key, const char *defval) { char *expression; char *retval; void *tree = NULL; RESULT result = { 0, 0, 0, NULL }; expression = cfg_lookup(section, key); if (expression != NULL) { if (*expression == '\0') return ""; if (Compile(expression, &tree) == 0 && Eval(tree, &result) == 0) { retval = strdup(R2S(&result)); DelTree(tree); DelResult(&result); return (retval); } DelTree(tree); DelResult(&result); } if (defval) return strdup(defval); return NULL; } The return value is either a pointer to a string or NULL. But while it is perfectly fine to call free(NULL), it is a segfault error to call free("") since "" is returned as a constant string. So in the case of *expression == '\0' one should have return strdup("") instead of return "" Am I correct? Bye! Mattia |
From: Mattia Jona-L. <mat...@gm...> - 2010-02-11 16:59:46
|
Hi The new plugin fifo is now in the repository with some bugfixes and improvements. The main differences are: - all static memory allocations are now dynamical - the plugin tries to match the internal buffer size with the number of display columns; if it fails then it can use a parameter supplied in the configuration file; if this parameter is absent then it uses a built in constant value - some off-by-one memory overflows have been fixed or avoided Bye! Mattia On Mon, Feb 8, 2010 at 12:32 PM, Mattia Jona-Lasinio <mat...@gm...> wrote: > Hi List! > > Ok, it seems that concerning the read(n) function, n being the number > of bytes to read, a lot of things can happen. This is what I found in > the docs. > > errno is a variable that specifies the type of error occured. This > means that for errno to be meaningful there MUST be an error. If > everything is fine then errno is undefined. > > read(n) is a function returning -1 in case of error or returning the > number of bytes that were read, if any (this number can be zero). It > is NOT considered an error if this number is less than n. Maybe we > reached the end of file or we were interrupted by the system. > > What you can count on is the following. > > If read(n) returns -1 then errno is set accordingly, to specify the error. > If read(n) returns n then everything went fine and errno is undefined. > > Here comes the "funny" part. > If errno == EINTR then we were interrupted by the system BUT it is > unspecified (POSIX allows for both behaviors) whether read must return > the number of bytes actually read or -1. And in the latter case it is > unspecified whether the file position is incremented or not so we > don't know whether we will reread the same data twice or we will read > new data. This is a killer!!! Anyway. As far as I know the Linux > implementation in case of an interruption by the system is to return > the bytes that were read and to set errno to EINTR, so we don't have > to worry about the file position but we cannot rely on read(n) < n to > assume errno is valid because, for example, if we are not interrupted > but simply we have a short read then read(n) < n but errno is not set > (undefined). > > So, to make a long story short we have three possible cases: > if read(n) == -1 then errno is valid. > if 0 <= read(n) < n then errno MIGHT be valid and set to EINTR. But in > the end who cares? Even if it were the case we also have the number of > bytes actually read and we have to treat them. So the errno == EINTR > case does not deserve a special treatment in the end. We might spot > this case by explicitely clearing errno (horrible! :) ) before calling > read, but then what? In any case we will be called again by the main > routine of lcd4linux. > if read(n) == n then errno is invalid. > > Since I heavily rewrote most of the code in a (to me) more rational > and better way, I send the complete plugin_fifo.c file instead of a > diff file. > And before committing it I'd like to have some feedback on it, to be > sure that the plugin has the intended behavior. Of course I'm open to > suggestions, improvements, criticisms, etc etc ;) > > Bye! > > Mattia > > On Thu, Feb 4, 2010 at 3:42 PM, Mattia Jona-Lasinio > <mat...@gm...> wrote: >> Hi Michael, >> >> I tried my solution but it does not solve completely the problem. I'm >> working on it and when I find an elegant solution, I will commit it. >> For the moment let's keep the errno = 0 patch. >> >> Bye, >> >> Mattia >> >> On Thu, Feb 4, 2010 at 3:31 PM, Michael Reinelt <mi...@re...> wrote: >>> Hi Mattia, >>> >>> thanks a bunch for pointing this out! I didn't read the code that careful (fortunately you did!), but I'm afraid even if >>> I did I would have missed this... >>> >>> as you already provided a clean solution, could you please check it in? >>> >>> >>> >>> TIA, Michael >>> >>> Mattia Jona-Lasinio schrieb: >>>> Hi Claas, Michael and The List! >>>> >>>> IMHO explicitely clearing the errno variable is generally a _VEEEEERY_ >>>> bad idea and should never be done. >>>> errno should be treated like a read only variable that one must assume >>>> to be completely undefined before a function that is allowed to modify >>>> it, is actually called. This means that its value must not be checked >>>> before calling the function that might change it, is actually called. >>>> And in any case the errno value must be checked only after checking >>>> the return value of the called function. >>>> Unfortunately in plugin_fifo.c, line 191 >>>> >>>> while (bytes > 0 && errno != EINTR) { >>>> bytes = read(fd.input, buf, FIFO_BUFFER_SIZE); >>>> } >>>> >>>> the value of errno is checked BEFORE the very first call to read. Then >>>> a previous function call might had set its value to EINTR and we are >>>> not going to read anything just because errno was spuriously set. In >>>> any case this piece of code is buggy because errno is set by read only >>>> if bytes < 0 OR 0 <= bytes < FIFO_BUFFER_SIZE, but is untouched >>>> (therefore still undefined) if bytes == FIFO_BUFFER_SIZE. >>>> >>>> But the solution is not clearing errno, but rather changing the code >>>> above to fix this bug. Something like >>>> >>>> while ((bytes = read(fd.input, buf, FIFO_BUFFER_SIZE)) > 0) { >>>> if (bytes < FIFO_BUFFER_SIZE && errno == EINTR) >>>> break; >>>> } >>>> >>>> so that the bytes = 1 initialization is not necessary. >>>> >>>> At this point the subsequent test >>>> >>>> if (bytes < 0 || (errno > 0 && errno != EAGAIN)) { >>>> error("[FIFO] Error %i: %s", errno, strerror(errno)); >>>> } >>>> >>>> becomes meaningful but one has to distinguish the cases "bytes < 0" >>>> (read returned an error) from "bytes < FIFO_BUFFER_SIZE" (there was >>>> just a "short" read), so that it should be something like >>>> >>>> if (bytes < 0 || (bytes < FIFO_BUFFER_SIZE && errno > 0 && errno != EAGAIN)) { >>>> error("[FIFO] Error %i: %s", errno, strerror(errno)); >>>> } >>>> >>>> >>>> What do you think about all this? >>>> >>>> >>>> Bye! >>>> >>>> >>>> Mattia >>>> >>>> >>>> >>>> On Thu, Feb 4, 2010 at 10:38 AM, Michael Reinelt <mi...@re...> wrote: >>>>> Applied! Thanks! >>>>> >>>>> Claas Hilbrecht schrieb: >>>>>> Hello, >>>>>> >>>>>> here is a very small fix (against current svn) for the plugin_fifo. You >>>>>> need to clear errno after creating the FIFO. Without clearing the errno >>>>>> variable you will get an error in fiforead() like this: >>>>>> >>>>>> [FIFO] Error 2: No such file or directory >>>>>> >>>>>> >>>>>> babel@eisler:~/tmp/lcd4linux$ svn diff plugin_fifo.c >>>>>> Index: plugin_fifo.c >>>>>> =================================================================== >>>>>> --- plugin_fifo.c (Revision 1097) >>>>>> +++ plugin_fifo.c (Arbeitskopie) >>>>>> @@ -110,6 +110,8 @@ >>>>>> error("Couldn't create FIFO \"%s\": %s\n", fd.path, >>>>>> strerror(errno)); >>>>>> return -1; >>>>>> } >>>>>> + /* clear errno */ >>>>>> + errno = 0; >>>>>> fd.created = 1; >>>>>> return 0; >>>>>> } >>>>>> >>>>>> Mit freundlichem Gruss >>>>>> Claas Hilbrecht >>>>>> >>>>>> >>>>>> ------------------------------------------------------------------------------ >>>>>> The Planet: dedicated and managed hosting, cloud storage, colocation >>>>>> Stay online with enterprise data centers and the best network in the business >>>>>> Choose flexible plans and management services without long-term contracts >>>>>> Personal 24x7 support from experience hosting pros just a phone call away. >>>>>> http://p.sf.net/sfu/theplanet-com >>>>>> _______________________________________________ >>>>>> Lcd4linux-devel mailing list >>>>>> Lcd...@li... >>>>>> https://lists.sourceforge.net/lists/listinfo/lcd4linux-devel >>>>>> >>>>>> >>>>> -- >>>>> Michael Reinelt <mi...@re...> >>>>> http://home.pages.at/reinelt >>>>> GPG-Key 0xDF13BA50 >>>>> ICQ #288386781 >>>>> >>>>> ------------------------------------------------------------------------------ >>>>> The Planet: dedicated and managed hosting, cloud storage, colocation >>>>> Stay online with enterprise data centers and the best network in the business >>>>> Choose flexible plans and management services without long-term contracts >>>>> Personal 24x7 support from experience hosting pros just a phone call away. >>>>> http://p.sf.net/sfu/theplanet-com >>>>> _______________________________________________ >>>>> Lcd4linux-devel mailing list >>>>> Lcd...@li... >>>>> https://lists.sourceforge.net/lists/listinfo/lcd4linux-devel >>>>> >>>> >>>> ------------------------------------------------------------------------------ >>>> The Planet: dedicated and managed hosting, cloud storage, colocation >>>> Stay online with enterprise data centers and the best network in the business >>>> Choose flexible plans and management services without long-term contracts >>>> Personal 24x7 support from experience hosting pros just a phone call away. >>>> http://p.sf.net/sfu/theplanet-com >>>> _______________________________________________ >>>> Lcd4linux-devel mailing list >>>> Lcd...@li... >>>> https://lists.sourceforge.net/lists/listinfo/lcd4linux-devel >>>> >>>> >>> >>> -- >>> Michael Reinelt <mi...@re...> >>> http://home.pages.at/reinelt >>> GPG-Key 0xDF13BA50 >>> ICQ #288386781 >>> >> > |
From: Martin Z. <co...@mz...> - 2010-02-09 20:28:27
|
Hi! After thinking about it, allowing anyone to write in /var/run/ (whether they are within the group "admin" or not) is a heavy security problem and shouldn't be done. Even running "lcd4linux" and thereby its python plugin as "root" is better, so I do that now. Sorry for my mistake. Martin -- www.mzuther.de www.radix-musik.de |
From: Martin Z. <co...@mz...> - 2010-02-09 20:22:32
|
Hi everybody, I have finally implemented and commented the code for syncing all timers. To make it more useful, I have placed this code in timer_inc(), which is now: static void timer_inc( struct timeval *timer, const struct timeval *now, const int interval, const short calculate_upcoming_event) The function is used to calculate the starting point of newly added timers and also to calculate the next triggering event for existing timers. I have tried to describe this behaviour in my last email. In short, it records the moment the first timer was started within "lcd4linux". Then, it uses this moment to quantise timer events using a timer's update interval: first timer: v second timer: * * * * * * quantisation: +---+---+---+---+---+---+--- second timer: * * * * * * This get's rid of the last synching problem, the differences in starting delay. For example, if you have to widgets with update intervals of 250 ms and 500 ms, respectively, you often got: 250 ms: * * * * * * * * * * * * 500 ms: * * * * * * Now you they are completely in sync: 250 ms: * * * * * * * * * * * * 500 ms: * * * * * * As a side note, the parameter "calculate_upcoming_event" is used to tell timer_inc() whether it should calculate the last time the timer triggered or the next time the timer will be triggered. This is all a bit hard to explain, but I hope that I gave you at least an idea of what I'm talking about. The new implementation of timer_inc() has one "problem" though: if you add a timer, the delay to first triggering event will usually be less than its update time. For example, if you add a timer of 400 ms, it might already trigger after 235 ms (afterwards, it will of course stick to the 400 ms). This is needed for quantisation and thus synchronisation of the timers, but I don't know if anybody needs "unsynched" timers that trigger *exactly* after the update time has passed. Which is the reason why I haven't yet committed my code. Actually, this is somewhat theoretical, because when I'm talking of "timing to the microsecond", I mean the times a timer *should* trigger, not the times it *does* trigger. This depends on things we can't influence, such as CPU utilisation and the time widgets need for updating. If you didn't get what the heck I'm talking about, please complain. Otherwise, tell me whether you see a need for "unsynched" timers or not. :) Thanks, Martin -- www.mzuther.de www.radix-musik.de |
From: Mattia Jona-L. <mat...@gm...> - 2010-02-08 11:33:03
|
Hi List! Ok, it seems that concerning the read(n) function, n being the number of bytes to read, a lot of things can happen. This is what I found in the docs. errno is a variable that specifies the type of error occured. This means that for errno to be meaningful there MUST be an error. If everything is fine then errno is undefined. read(n) is a function returning -1 in case of error or returning the number of bytes that were read, if any (this number can be zero). It is NOT considered an error if this number is less than n. Maybe we reached the end of file or we were interrupted by the system. What you can count on is the following. If read(n) returns -1 then errno is set accordingly, to specify the error. If read(n) returns n then everything went fine and errno is undefined. Here comes the "funny" part. If errno == EINTR then we were interrupted by the system BUT it is unspecified (POSIX allows for both behaviors) whether read must return the number of bytes actually read or -1. And in the latter case it is unspecified whether the file position is incremented or not so we don't know whether we will reread the same data twice or we will read new data. This is a killer!!! Anyway. As far as I know the Linux implementation in case of an interruption by the system is to return the bytes that were read and to set errno to EINTR, so we don't have to worry about the file position but we cannot rely on read(n) < n to assume errno is valid because, for example, if we are not interrupted but simply we have a short read then read(n) < n but errno is not set (undefined). So, to make a long story short we have three possible cases: if read(n) == -1 then errno is valid. if 0 <= read(n) < n then errno MIGHT be valid and set to EINTR. But in the end who cares? Even if it were the case we also have the number of bytes actually read and we have to treat them. So the errno == EINTR case does not deserve a special treatment in the end. We might spot this case by explicitely clearing errno (horrible! :) ) before calling read, but then what? In any case we will be called again by the main routine of lcd4linux. if read(n) == n then errno is invalid. Since I heavily rewrote most of the code in a (to me) more rational and better way, I send the complete plugin_fifo.c file instead of a diff file. And before committing it I'd like to have some feedback on it, to be sure that the plugin has the intended behavior. Of course I'm open to suggestions, improvements, criticisms, etc etc ;) Bye! Mattia On Thu, Feb 4, 2010 at 3:42 PM, Mattia Jona-Lasinio <mat...@gm...> wrote: > Hi Michael, > > I tried my solution but it does not solve completely the problem. I'm > working on it and when I find an elegant solution, I will commit it. > For the moment let's keep the errno = 0 patch. > > Bye, > > Mattia > > On Thu, Feb 4, 2010 at 3:31 PM, Michael Reinelt <mi...@re...> wrote: >> Hi Mattia, >> >> thanks a bunch for pointing this out! I didn't read the code that careful (fortunately you did!), but I'm afraid even if >> I did I would have missed this... >> >> as you already provided a clean solution, could you please check it in? >> >> >> >> TIA, Michael >> >> Mattia Jona-Lasinio schrieb: >>> Hi Claas, Michael and The List! >>> >>> IMHO explicitely clearing the errno variable is generally a _VEEEEERY_ >>> bad idea and should never be done. >>> errno should be treated like a read only variable that one must assume >>> to be completely undefined before a function that is allowed to modify >>> it, is actually called. This means that its value must not be checked >>> before calling the function that might change it, is actually called. >>> And in any case the errno value must be checked only after checking >>> the return value of the called function. >>> Unfortunately in plugin_fifo.c, line 191 >>> >>> while (bytes > 0 && errno != EINTR) { >>> bytes = read(fd.input, buf, FIFO_BUFFER_SIZE); >>> } >>> >>> the value of errno is checked BEFORE the very first call to read. Then >>> a previous function call might had set its value to EINTR and we are >>> not going to read anything just because errno was spuriously set. In >>> any case this piece of code is buggy because errno is set by read only >>> if bytes < 0 OR 0 <= bytes < FIFO_BUFFER_SIZE, but is untouched >>> (therefore still undefined) if bytes == FIFO_BUFFER_SIZE. >>> >>> But the solution is not clearing errno, but rather changing the code >>> above to fix this bug. Something like >>> >>> while ((bytes = read(fd.input, buf, FIFO_BUFFER_SIZE)) > 0) { >>> if (bytes < FIFO_BUFFER_SIZE && errno == EINTR) >>> break; >>> } >>> >>> so that the bytes = 1 initialization is not necessary. >>> >>> At this point the subsequent test >>> >>> if (bytes < 0 || (errno > 0 && errno != EAGAIN)) { >>> error("[FIFO] Error %i: %s", errno, strerror(errno)); >>> } >>> >>> becomes meaningful but one has to distinguish the cases "bytes < 0" >>> (read returned an error) from "bytes < FIFO_BUFFER_SIZE" (there was >>> just a "short" read), so that it should be something like >>> >>> if (bytes < 0 || (bytes < FIFO_BUFFER_SIZE && errno > 0 && errno != EAGAIN)) { >>> error("[FIFO] Error %i: %s", errno, strerror(errno)); >>> } >>> >>> >>> What do you think about all this? >>> >>> >>> Bye! >>> >>> >>> Mattia >>> >>> >>> >>> On Thu, Feb 4, 2010 at 10:38 AM, Michael Reinelt <mi...@re...> wrote: >>>> Applied! Thanks! >>>> >>>> Claas Hilbrecht schrieb: >>>>> Hello, >>>>> >>>>> here is a very small fix (against current svn) for the plugin_fifo. You >>>>> need to clear errno after creating the FIFO. Without clearing the errno >>>>> variable you will get an error in fiforead() like this: >>>>> >>>>> [FIFO] Error 2: No such file or directory >>>>> >>>>> >>>>> babel@eisler:~/tmp/lcd4linux$ svn diff plugin_fifo.c >>>>> Index: plugin_fifo.c >>>>> =================================================================== >>>>> --- plugin_fifo.c (Revision 1097) >>>>> +++ plugin_fifo.c (Arbeitskopie) >>>>> @@ -110,6 +110,8 @@ >>>>> error("Couldn't create FIFO \"%s\": %s\n", fd.path, >>>>> strerror(errno)); >>>>> return -1; >>>>> } >>>>> + /* clear errno */ >>>>> + errno = 0; >>>>> fd.created = 1; >>>>> return 0; >>>>> } >>>>> >>>>> Mit freundlichem Gruss >>>>> Claas Hilbrecht >>>>> >>>>> >>>>> ------------------------------------------------------------------------------ >>>>> The Planet: dedicated and managed hosting, cloud storage, colocation >>>>> Stay online with enterprise data centers and the best network in the business >>>>> Choose flexible plans and management services without long-term contracts >>>>> Personal 24x7 support from experience hosting pros just a phone call away. >>>>> http://p.sf.net/sfu/theplanet-com >>>>> _______________________________________________ >>>>> Lcd4linux-devel mailing list >>>>> Lcd...@li... >>>>> https://lists.sourceforge.net/lists/listinfo/lcd4linux-devel >>>>> >>>>> >>>> -- >>>> Michael Reinelt <mi...@re...> >>>> http://home.pages.at/reinelt >>>> GPG-Key 0xDF13BA50 >>>> ICQ #288386781 >>>> >>>> ------------------------------------------------------------------------------ >>>> The Planet: dedicated and managed hosting, cloud storage, colocation >>>> Stay online with enterprise data centers and the best network in the business >>>> Choose flexible plans and management services without long-term contracts >>>> Personal 24x7 support from experience hosting pros just a phone call away. >>>> http://p.sf.net/sfu/theplanet-com >>>> _______________________________________________ >>>> Lcd4linux-devel mailing list >>>> Lcd...@li... >>>> https://lists.sourceforge.net/lists/listinfo/lcd4linux-devel >>>> >>> >>> ------------------------------------------------------------------------------ >>> The Planet: dedicated and managed hosting, cloud storage, colocation >>> Stay online with enterprise data centers and the best network in the business >>> Choose flexible plans and management services without long-term contracts >>> Personal 24x7 support from experience hosting pros just a phone call away. >>> http://p.sf.net/sfu/theplanet-com >>> _______________________________________________ >>> Lcd4linux-devel mailing list >>> Lcd...@li... >>> https://lists.sourceforge.net/lists/listinfo/lcd4linux-devel >>> >>> >> >> -- >> Michael Reinelt <mi...@re...> >> http://home.pages.at/reinelt >> GPG-Key 0xDF13BA50 >> ICQ #288386781 >> > |
From: Martin Z. <co...@mz...> - 2010-02-07 21:23:39
|
Dear Michael, I might have had the sense to look at syslog myself. Anyway, I'm not running "lcd4linux" as root and the directory permissions on my Debian-based systems were too restrictive: mkstemp(/var/run/lcd4linux.pid.6X3ybP) failed: Permission denied For users who stumble across this -- I simply changed the permissions of "/var/run" by the commands: sudo chown root:admin /var/run/ sudo chmod 775 /var/run/ and everything's fine again. Although this relaxes security a little, users runnning "lcd4linux" still have to be in the group "admin" to write to "/var/run". Thanks, Martin P.S.: Is everybody *really* running "lcd4linux" as root?!? -- www.mzuther.de www.radix-musik.de |
From: Michael R. <mi...@re...> - 2010-02-07 14:59:38
|
Hi Martin, > As of new, "lcd4linux" (from SVN) doesn't run unless I specify the "-F" > command line option. It starts, but it directly quits. I.e., > > # lcd4linux -Fq > # pgrep -l lcd > 10968 lcd4linux > > runs, but > > # lcd4linux -q > # pgrep -l lcd > > does not. Any ideas? Huh? Never seen that before... as lcd4linux should use syslog, any hints from there? > That was a pretty short email for me, wasn't it? ;) /* no comment */ bye, Michael -- Michael Reinelt <mi...@re...> http://home.pages.at/reinelt GPG-Key 0xDF13BA50 ICQ #288386781 |
From: Martin Z. <co...@mz...> - 2010-02-07 14:20:21
|
Hi! As of new, "lcd4linux" (from SVN) doesn't run unless I specify the "-F" command line option. It starts, but it directly quits. I.e., # lcd4linux -Fq # pgrep -l lcd 10968 lcd4linux runs, but # lcd4linux -q # pgrep -l lcd does not. Any ideas? That was a pretty short email for me, wasn't it? ;) Martin -- www.mzuther.de www.radix-musik.de |
From: Martin Z. <co...@mz...> - 2010-02-07 14:09:36
|
Hi Michael, you're still a little hesitant (and I can understand that), but I'll get you in the end. :) Thanks -- I have finally understood where all the one-shot timers come from. I never had the time to more than glance at the widget code. But couldn't the "dynamic value update" (which is great and I want to keep as well!) somehow be done during the update callback function? Anyway, yesterday I *did* write some code to sync all timers. What it does is (again) easy but works quite well. When the first timer is started, a global timeval called "timer_sync_base" is set to the current date and time by gettimeofday(). After that, this global value is never touched again. Now, when a new timer is added, my code calculates the number of updates that have happened since "timer_sync_base" and also the time difference that corresponds to this number of updates. This time difference is then added to "timer_sync_base", and finally the timer's "update" value is set to the result. I think, an example is in order (to keep it easy, update interval is one second): 1265490677.167110 first timer is added "timer_sync_base" is set to 1265490677.167110 timer variable "update" is set to 1265490677.167110 1265490678.171091 first timer triggers (initialisation; this is your "old" code) 1265490678.167110 first timer triggers (one second since timer base) 1265490678.671346 second timer is added code calculates that one update has already passed timer variable "update" is set to 1265490678.167110 (one second after "timer_sync_base") 1265490678.698234 second timer triggers (intialisation; this again is your "old" code) 1265490679.167110 first timer triggers (two seconds since timer base) 1265490679.167110 second timer triggers (two seconds since timer base) I have found some easy mathematics to calculate the number of passed updates, so this does not interfere with performance. The code works, but it needs cleaning up and commenting. Right now, I'm probably the only one who'd understand it. ;) > I'm afraid I did miss that patch you are mentioning... wasn't it that "timer_group" stuff? Isn't it necessary to replace > the timer_add() call in the widget code? Yes, that's the one I meant. While you don't exactly need this grouping of timers, it *does* reduce overhead by creating only one timer per group, and this group timer is even continuous. The timer_add() call in the widget code would have to be changed to timer_add_widget(), of course, but the widgets do keep their one-shot timers. So as I said, the widget code wouldn't have to change at all, but we'd get rid of all the one-shot-timer overhead. As a side effect, the groups also ensure that all widgets in a group are updated simultaneously. This effect could also be used for LCDs that only write to a framebuffer and are then updated as a whole, because you could implement a function called update_all() that would be called after all widgets within a group have been updated. This function would have to be in all drivers and would usually be empty. But in drivers that update the whole display, this function would then write the frame buffer to the LCD, getting rid of the timer that is currently needed to regularly copy the frame buffer to the display. You see, I have put some thought into all this, because my LCD is *really* slow when it is updated... :) Given all these advantages, I have finally committed my patch for grouping widgets. I don't know if I've got the copyrights correct -- please feel free to correct them. > but: if there is no more timeshift, how can widgets get unsync? Yes, you're right (if there is no initial delay, but as I say, I'm on my way to fixing this). I think there might be problems with the overhead of creating all those one-shot timers, but I'm in no way able to describe them. Let's say, they are similar to a foreboding... ;) > please, please, don't get me wrong: I in no way dislike your patch. I just want to solve it for *all* timers, not only > widget updates. I didn't get you wrong at all. I know what you're driving at, and I think we're on our way to solve the problem. :) Greetings from snowy Hamburg, Martin -- www.mzuther.de www.radix-musik.de |
From: Michael R. <mi...@re...> - 2010-02-07 05:52:02
|
Hi Martin! another thing came to my mind: your patches will not help getting one-shot timers to go out of sync? As we are basically increasing the timeout value of a timer, and compensate processing delays, this won't work for one-shot timers, because there is nothing to increase... If we want to keep the "dynamic update values" which can be changed at runtime (and I think I want to), maybe a "timer_mod()" function to set a new update interval would solve this? (and avoid the overhead to delete and recreate the timer) bye, Michael -- Michael Reinelt <mi...@re...> http://home.pages.at/reinelt GPG-Key 0xDF13BA50 ICQ #288386781 |
From: Michael R. <mi...@re...> - 2010-02-07 05:44:04
|
Hi Martin! > To be honest, I don't... :) Well, I think you're not alone ;-) > First, I think we have to define the problem, because in my opinion there are two of them that need separate solving. > One is the time-shift that is introduced by processing. The other one is that of unsynchronised widgets, and I have > already solved that, at least partially. So let's talk about time-shifts. Correct. > First, using one-shot timers for widgets doesn't seem to make sense to me. First, there is the overhead of deleting > the old one and creating a new one. Second, most (if not all) widgets are triggered regularly, so using one-shot > timers isn't the best solution. That's not true, at least not at all. At the moment, only two o three widgets use one-shot timers, just because the other widgets haven't been ported to use "Properties" yet. A "property" is a widget attribute from the config file, which is evaluated at every update (and not only once when initializing the widget). I'd like to call them "dynamic attributes" because they may change at runtime. A (simple) example would be "update is_night()? 500 : 100" > First, have a look at line 182, which is where a single *continuous* timer is being respawned: > > } else { Timers[i].when = now; timer_inc(&Timers[i].when, Timers[i].interval); } > > I think the second line (which sets the timer to "now") is plain wrong because it automatically delays a timer by the > time the callback needs for processing. So this line should be removed as fast as possible! It took me some time to understand it, but you are absolutely right! > Another, albeit smaller, problem lies in line 206: > > /* delay until next timer event */ struct timeval diff; timersub(&Timers[min].when, &now, &diff); > > delay->tv_sec = diff.tv_sec; /* microseconds to nanoseconds!! */ delay->tv_nsec = diff.tv_usec * 1000; > > Here, the delay to the next timer event is too long, because we ignore the processing time between reading the value > for "now" and calculating the delay. What we need here is to update the value for "now" and only then calculate the > delay: > > /* delay until next timer event */ struct timeval diff; timersub(&Timers[min].when, &now, &diff); gettimeofday(&now, > NULL); Again, you are right. > So it seems that we don't need any "processing magic" at all. Just convert the widgets to continuous timers and make > the two changes in "timer.c", and we're set! Actually, I didn't think it was *that* easy, and maybe I have overseen > something -- but maybe that's just it! :) Great! So the timers should work correctly now, and there should be no mor time-shifts, right? And now for your 2nd mail: > Moreover, I have found out that you don't even have to change any single line in the widget code if you apply the > patch for synchronising widgets I have sent before. I have applied this patch, and now the widgets are synced (at > least within their respective groups) and the timers are correct to the microsecond! I'm afraid I did miss that patch you are mentioning... wasn't it that "timer_group" stuff? Isn't it necessary to replace the timer_add() call in the widget code? > I repeat my old question: shall I commit, or shan't I commit? ;) I can't answer because... (see above) but: if there is no more timeshift, how can widgets get unsync? OTOH: please consider two things: the "initial delay" and the "properties" stuff from above. please, please, don't get me wrong: I in no way dislike your patch. I just want to solve it for *all* timers, not only widget updates. bye, Michael -- Michael Reinelt <mi...@re...> http://home.pages.at/reinelt GPG-Key 0xDF13BA50 ICQ #288386781 |
From: Martin Z. <co...@mz...> - 2010-02-06 22:26:51
|
Hi everybody, I have just committed the two small but efficient changes in "timer.c" that I mentioned in my last email. Moreover, I have found out that you don't even have to change any single line in the widget code if you apply the patch for synchronising widgets I have sent before. I have applied this patch, and now the widgets are synced (at least within their respective groups) and the timers are correct to the microsecond! Here's the -- hmmm -- not so short output from a real world example (the LCD control for my media server, to be exact), run for 20 seconds and then sorted by timer id: timer.c: Timer[ 1]: 1265494167.034760 timer.c: Timer[ 1]: 1265494167.134760 timer.c: Timer[ 1]: 1265494167.234760 timer.c: Timer[ 1]: 1265494167.334760 timer.c: Timer[ 1]: 1265494167.434760 timer.c: Timer[ 1]: 1265494167.534760 timer.c: Timer[ 1]: 1265494167.634760 timer.c: Timer[ 1]: 1265494167.734760 timer.c: Timer[ 1]: 1265494167.834760 timer.c: Timer[ 1]: 1265494167.934760 timer.c: Timer[ 1]: 1265494168.034760 timer.c: Timer[ 1]: 1265494168.134760 timer.c: Timer[ 1]: 1265494168.234760 timer.c: Timer[ 1]: 1265494168.334760 timer.c: Timer[ 1]: 1265494168.434760 timer.c: Timer[ 1]: 1265494168.534760 timer.c: Timer[ 1]: 1265494168.634760 timer.c: Timer[ 1]: 1265494168.734760 timer.c: Timer[ 1]: 1265494168.834760 timer.c: Timer[ 1]: 1265494168.934760 timer.c: Timer[ 1]: 1265494169.034760 timer.c: Timer[ 1]: 1265494169.134760 timer.c: Timer[ 1]: 1265494169.234760 timer.c: Timer[ 1]: 1265494169.334760 timer.c: Timer[ 1]: 1265494169.434760 timer.c: Timer[ 1]: 1265494169.534760 timer.c: Timer[ 1]: 1265494169.634760 timer.c: Timer[ 1]: 1265494169.734760 timer.c: Timer[ 1]: 1265494169.834760 timer.c: Timer[ 1]: 1265494169.934760 timer.c: Timer[ 1]: 1265494170.034760 timer.c: Timer[ 1]: 1265494170.134760 timer.c: Timer[ 1]: 1265494170.234760 timer.c: Timer[ 1]: 1265494170.334760 timer.c: Timer[ 1]: 1265494170.434760 timer.c: Timer[ 1]: 1265494170.534760 timer.c: Timer[ 1]: 1265494170.634760 timer.c: Timer[ 1]: 1265494170.734760 timer.c: Timer[ 1]: 1265494170.834760 timer.c: Timer[ 1]: 1265494170.934760 timer.c: Timer[ 1]: 1265494171.034760 timer.c: Timer[ 1]: 1265494171.134760 timer.c: Timer[ 1]: 1265494171.234760 timer.c: Timer[ 1]: 1265494171.334760 timer.c: Timer[ 1]: 1265494171.434760 timer.c: Timer[ 1]: 1265494171.534760 timer.c: Timer[ 1]: 1265494171.634760 timer.c: Timer[ 1]: 1265494171.734760 timer.c: Timer[ 1]: 1265494171.834760 timer.c: Timer[ 1]: 1265494171.934760 timer.c: Timer[ 1]: 1265494172.034760 timer.c: Timer[ 1]: 1265494172.134760 timer.c: Timer[ 1]: 1265494172.234760 timer.c: Timer[ 1]: 1265494172.334760 timer.c: Timer[ 1]: 1265494172.434760 timer.c: Timer[ 1]: 1265494172.534760 timer.c: Timer[ 1]: 1265494172.634760 timer.c: Timer[ 1]: 1265494172.734760 timer.c: Timer[ 1]: 1265494172.834760 timer.c: Timer[ 1]: 1265494172.934760 timer.c: Timer[ 1]: 1265494173.034760 timer.c: Timer[ 1]: 1265494173.134760 timer.c: Timer[ 1]: 1265494173.234760 timer.c: Timer[ 1]: 1265494173.334760 timer.c: Timer[ 1]: 1265494173.434760 timer.c: Timer[ 1]: 1265494173.534760 timer.c: Timer[ 1]: 1265494173.634760 timer.c: Timer[ 1]: 1265494173.734760 timer.c: Timer[ 1]: 1265494173.834760 timer.c: Timer[ 1]: 1265494173.934760 timer.c: Timer[ 1]: 1265494174.034760 timer.c: Timer[ 1]: 1265494174.134760 timer.c: Timer[ 1]: 1265494174.234760 timer.c: Timer[ 1]: 1265494174.334760 timer.c: Timer[ 1]: 1265494174.434760 timer.c: Timer[ 1]: 1265494174.534760 timer.c: Timer[ 1]: 1265494174.634760 timer.c: Timer[ 1]: 1265494174.734760 timer.c: Timer[ 1]: 1265494174.834760 timer.c: Timer[ 1]: 1265494174.934760 timer.c: Timer[ 1]: 1265494175.034760 timer.c: Timer[ 1]: 1265494175.134760 timer.c: Timer[ 1]: 1265494175.234760 timer.c: Timer[ 1]: 1265494175.334760 timer.c: Timer[ 1]: 1265494175.434760 timer.c: Timer[ 1]: 1265494175.534760 timer.c: Timer[ 1]: 1265494175.634760 timer.c: Timer[ 1]: 1265494175.734760 timer.c: Timer[ 1]: 1265494175.834760 timer.c: Timer[ 1]: 1265494175.934760 timer.c: Timer[ 1]: 1265494176.034760 timer.c: Timer[ 1]: 1265494176.134760 timer.c: Timer[ 1]: 1265494176.234760 timer.c: Timer[ 1]: 1265494176.334760 timer.c: Timer[ 1]: 1265494176.434760 timer.c: Timer[ 1]: 1265494176.534760 timer.c: Timer[ 1]: 1265494176.634760 timer.c: Timer[ 1]: 1265494176.734760 timer.c: Timer[ 1]: 1265494176.834760 timer.c: Timer[ 1]: 1265494176.934760 timer.c: Timer[ 1]: 1265494177.034760 timer.c: Timer[ 1]: 1265494177.134760 timer.c: Timer[ 1]: 1265494177.234760 timer.c: Timer[ 1]: 1265494177.334760 timer.c: Timer[ 1]: 1265494177.434760 timer.c: Timer[ 1]: 1265494177.534760 timer.c: Timer[ 1]: 1265494177.634760 timer.c: Timer[ 1]: 1265494177.734760 timer.c: Timer[ 1]: 1265494177.834760 timer.c: Timer[ 1]: 1265494177.934760 timer.c: Timer[ 1]: 1265494178.034760 timer.c: Timer[ 1]: 1265494178.134760 timer.c: Timer[ 1]: 1265494178.234760 timer.c: Timer[ 1]: 1265494178.334760 timer.c: Timer[ 1]: 1265494178.434760 timer.c: Timer[ 1]: 1265494178.534760 timer.c: Timer[ 1]: 1265494178.634760 timer.c: Timer[ 1]: 1265494178.734760 timer.c: Timer[ 1]: 1265494178.834760 timer.c: Timer[ 1]: 1265494178.934760 timer.c: Timer[ 1]: 1265494179.034760 timer.c: Timer[ 1]: 1265494179.134760 timer.c: Timer[ 1]: 1265494179.234760 timer.c: Timer[ 1]: 1265494179.334760 timer.c: Timer[ 1]: 1265494179.434760 timer.c: Timer[ 1]: 1265494179.534760 timer.c: Timer[ 1]: 1265494179.634760 timer.c: Timer[ 1]: 1265494179.734760 timer.c: Timer[ 1]: 1265494179.834760 timer.c: Timer[ 1]: 1265494179.934760 timer.c: Timer[ 1]: 1265494180.034760 timer.c: Timer[ 1]: 1265494180.134760 timer.c: Timer[ 1]: 1265494180.234760 timer.c: Timer[ 1]: 1265494180.334760 timer.c: Timer[ 1]: 1265494180.434760 timer.c: Timer[ 1]: 1265494180.534760 timer.c: Timer[ 1]: 1265494180.634760 timer.c: Timer[ 1]: 1265494180.734760 timer.c: Timer[ 1]: 1265494180.834760 timer.c: Timer[ 1]: 1265494180.934760 timer.c: Timer[ 1]: 1265494181.034760 timer.c: Timer[ 1]: 1265494181.134760 timer.c: Timer[ 1]: 1265494181.234760 timer.c: Timer[ 1]: 1265494181.334760 timer.c: Timer[ 1]: 1265494181.434760 timer.c: Timer[ 1]: 1265494181.534760 timer.c: Timer[ 1]: 1265494181.634760 timer.c: Timer[ 1]: 1265494181.734760 timer.c: Timer[ 1]: 1265494181.834760 timer.c: Timer[ 1]: 1265494181.934760 timer.c: Timer[ 1]: 1265494182.034760 timer.c: Timer[ 1]: 1265494182.134760 timer.c: Timer[ 1]: 1265494182.234760 timer.c: Timer[ 1]: 1265494182.334760 timer.c: Timer[ 1]: 1265494182.434760 timer.c: Timer[ 1]: 1265494182.534760 timer.c: Timer[ 1]: 1265494182.634760 timer.c: Timer[ 1]: 1265494182.734760 timer.c: Timer[ 1]: 1265494182.834760 timer.c: Timer[ 1]: 1265494182.934760 timer.c: Timer[ 1]: 1265494183.034760 timer.c: Timer[ 1]: 1265494183.134760 timer.c: Timer[ 1]: 1265494183.234760 timer.c: Timer[ 1]: 1265494183.334760 timer.c: Timer[ 1]: 1265494183.434760 timer.c: Timer[ 1]: 1265494183.534760 timer.c: Timer[ 1]: 1265494183.634760 timer.c: Timer[ 1]: 1265494183.734760 timer.c: Timer[ 1]: 1265494183.834760 timer.c: Timer[ 1]: 1265494183.934760 timer.c: Timer[ 1]: 1265494184.034760 timer.c: Timer[ 1]: 1265494184.134760 timer.c: Timer[ 1]: 1265494184.234760 timer.c: Timer[ 1]: 1265494184.334760 timer.c: Timer[ 1]: 1265494184.434760 timer.c: Timer[ 1]: 1265494184.534760 timer.c: Timer[ 1]: 1265494184.634760 timer.c: Timer[ 1]: 1265494184.734760 timer.c: Timer[ 1]: 1265494184.834760 timer.c: Timer[ 1]: 1265494184.934760 timer.c: Timer[ 1]: 1265494185.034760 timer.c: Timer[ 1]: 1265494185.134760 timer.c: Timer[ 1]: 1265494185.234760 timer.c: Timer[ 1]: 1265494185.334760 timer.c: Timer[ 1]: 1265494185.434760 timer.c: Timer[ 1]: 1265494185.534760 timer.c: Timer[ 1]: 1265494185.634760 timer.c: Timer[ 1]: 1265494185.734760 timer.c: Timer[ 1]: 1265494185.834760 timer.c: Timer[ 1]: 1265494185.934760 timer.c: Timer[ 1]: 1265494186.034760 timer.c: Timer[ 1]: 1265494186.134760 timer.c: Timer[ 1]: 1265494186.234760 timer.c: Timer[ 1]: 1265494186.334760 timer.c: Timer[ 1]: 1265494186.434760 timer.c: Timer[ 1]: 1265494186.534760 timer.c: Timer[ 1]: 1265494186.634760 timer.c: Timer[ 1]: 1265494186.734760 timer.c: Timer[ 1]: 1265494186.834760 timer.c: Timer[ 1]: 1265494186.934760 timer.c: Timer[ 1]: 1265494187.034760 timer.c: Timer[ 1]: 1265494187.134760 timer.c: Timer[ 1]: 1265494187.234760 timer.c: Timer[ 1]: 1265494187.334760 timer.c: Timer[ 1]: 1265494187.434760 timer.c: Timer[ 1]: 1265494187.534760 timer.c: Timer[ 1]: 1265494187.634760 timer.c: Timer[ 1]: 1265494187.734760 timer.c: Timer[ 1]: 1265494187.834760 timer.c: Timer[ 1]: 1265494187.934760 timer.c: Timer[ 2]: 1265494166.970222 timer.c: Timer[ 2]: 1265494167.220222 timer.c: Timer[ 2]: 1265494167.470222 timer.c: Timer[ 2]: 1265494167.720222 timer.c: Timer[ 2]: 1265494167.970222 timer.c: Timer[ 2]: 1265494168.220222 timer.c: Timer[ 2]: 1265494168.470222 timer.c: Timer[ 2]: 1265494168.720222 timer.c: Timer[ 2]: 1265494168.970222 timer.c: Timer[ 2]: 1265494169.220222 timer.c: Timer[ 2]: 1265494169.470222 timer.c: Timer[ 2]: 1265494169.720222 timer.c: Timer[ 2]: 1265494169.970222 timer.c: Timer[ 2]: 1265494170.220222 timer.c: Timer[ 2]: 1265494170.470222 timer.c: Timer[ 2]: 1265494170.720222 timer.c: Timer[ 2]: 1265494170.970222 timer.c: Timer[ 2]: 1265494171.220222 timer.c: Timer[ 2]: 1265494171.470222 timer.c: Timer[ 2]: 1265494171.720222 timer.c: Timer[ 2]: 1265494171.970222 timer.c: Timer[ 2]: 1265494172.220222 timer.c: Timer[ 2]: 1265494172.470222 timer.c: Timer[ 2]: 1265494172.720222 timer.c: Timer[ 2]: 1265494172.970222 timer.c: Timer[ 2]: 1265494173.220222 timer.c: Timer[ 2]: 1265494173.470222 timer.c: Timer[ 2]: 1265494173.720222 timer.c: Timer[ 2]: 1265494173.970222 timer.c: Timer[ 2]: 1265494174.220222 timer.c: Timer[ 2]: 1265494174.470222 timer.c: Timer[ 2]: 1265494174.720222 timer.c: Timer[ 2]: 1265494174.970222 timer.c: Timer[ 2]: 1265494175.220222 timer.c: Timer[ 2]: 1265494175.470222 timer.c: Timer[ 2]: 1265494175.720222 timer.c: Timer[ 2]: 1265494175.970222 timer.c: Timer[ 2]: 1265494176.220222 timer.c: Timer[ 2]: 1265494176.470222 timer.c: Timer[ 2]: 1265494176.720222 timer.c: Timer[ 2]: 1265494176.970222 timer.c: Timer[ 2]: 1265494177.220222 timer.c: Timer[ 2]: 1265494177.470222 timer.c: Timer[ 2]: 1265494177.720222 timer.c: Timer[ 2]: 1265494177.970222 timer.c: Timer[ 2]: 1265494178.220222 timer.c: Timer[ 2]: 1265494178.470222 timer.c: Timer[ 2]: 1265494178.720222 timer.c: Timer[ 2]: 1265494178.970222 timer.c: Timer[ 2]: 1265494179.220222 timer.c: Timer[ 2]: 1265494179.470222 timer.c: Timer[ 2]: 1265494179.720222 timer.c: Timer[ 2]: 1265494179.970222 timer.c: Timer[ 2]: 1265494180.220222 timer.c: Timer[ 2]: 1265494180.470222 timer.c: Timer[ 2]: 1265494180.720222 timer.c: Timer[ 2]: 1265494180.970222 timer.c: Timer[ 2]: 1265494181.220222 timer.c: Timer[ 2]: 1265494181.470222 timer.c: Timer[ 2]: 1265494181.720222 timer.c: Timer[ 2]: 1265494181.970222 timer.c: Timer[ 2]: 1265494182.220222 timer.c: Timer[ 2]: 1265494182.470222 timer.c: Timer[ 2]: 1265494182.720222 timer.c: Timer[ 2]: 1265494182.970222 timer.c: Timer[ 2]: 1265494183.220222 timer.c: Timer[ 2]: 1265494183.470222 timer.c: Timer[ 2]: 1265494183.720222 timer.c: Timer[ 2]: 1265494183.970222 timer.c: Timer[ 2]: 1265494184.220222 timer.c: Timer[ 2]: 1265494184.470222 timer.c: Timer[ 2]: 1265494184.720222 timer.c: Timer[ 2]: 1265494184.970222 timer.c: Timer[ 2]: 1265494185.220222 timer.c: Timer[ 2]: 1265494185.470222 timer.c: Timer[ 2]: 1265494185.720222 timer.c: Timer[ 2]: 1265494185.970222 timer.c: Timer[ 2]: 1265494186.220222 timer.c: Timer[ 2]: 1265494186.470222 timer.c: Timer[ 2]: 1265494186.720222 timer.c: Timer[ 2]: 1265494186.970222 timer.c: Timer[ 2]: 1265494187.220222 timer.c: Timer[ 2]: 1265494187.470222 timer.c: Timer[ 2]: 1265494187.720222 timer.c: Timer[ 3]: 1265494166.970265 timer.c: Timer[ 3]: 1265494167.220265 timer.c: Timer[ 3]: 1265494167.470265 timer.c: Timer[ 3]: 1265494167.720265 timer.c: Timer[ 3]: 1265494167.970265 timer.c: Timer[ 3]: 1265494168.220265 timer.c: Timer[ 3]: 1265494168.470265 timer.c: Timer[ 3]: 1265494168.720265 timer.c: Timer[ 3]: 1265494168.970265 timer.c: Timer[ 3]: 1265494169.220265 timer.c: Timer[ 3]: 1265494169.470265 timer.c: Timer[ 3]: 1265494169.720265 timer.c: Timer[ 3]: 1265494169.970265 timer.c: Timer[ 3]: 1265494170.220265 timer.c: Timer[ 3]: 1265494170.470265 timer.c: Timer[ 3]: 1265494170.720265 timer.c: Timer[ 3]: 1265494170.970265 timer.c: Timer[ 3]: 1265494171.220265 timer.c: Timer[ 3]: 1265494171.470265 timer.c: Timer[ 3]: 1265494171.720265 timer.c: Timer[ 3]: 1265494171.970265 timer.c: Timer[ 3]: 1265494172.220265 timer.c: Timer[ 3]: 1265494172.470265 timer.c: Timer[ 3]: 1265494172.720265 timer.c: Timer[ 3]: 1265494172.970265 timer.c: Timer[ 3]: 1265494173.220265 timer.c: Timer[ 3]: 1265494173.470265 timer.c: Timer[ 3]: 1265494173.720265 timer.c: Timer[ 3]: 1265494173.970265 timer.c: Timer[ 3]: 1265494174.220265 timer.c: Timer[ 3]: 1265494174.470265 timer.c: Timer[ 3]: 1265494174.720265 timer.c: Timer[ 3]: 1265494174.970265 timer.c: Timer[ 3]: 1265494175.220265 timer.c: Timer[ 3]: 1265494175.470265 timer.c: Timer[ 3]: 1265494175.720265 timer.c: Timer[ 3]: 1265494175.970265 timer.c: Timer[ 3]: 1265494176.220265 timer.c: Timer[ 3]: 1265494176.470265 timer.c: Timer[ 3]: 1265494176.720265 timer.c: Timer[ 3]: 1265494176.970265 timer.c: Timer[ 3]: 1265494177.220265 timer.c: Timer[ 3]: 1265494177.470265 timer.c: Timer[ 3]: 1265494177.720265 timer.c: Timer[ 3]: 1265494177.970265 timer.c: Timer[ 3]: 1265494178.220265 timer.c: Timer[ 3]: 1265494178.470265 timer.c: Timer[ 3]: 1265494178.720265 timer.c: Timer[ 3]: 1265494178.970265 timer.c: Timer[ 3]: 1265494179.220265 timer.c: Timer[ 3]: 1265494179.470265 timer.c: Timer[ 3]: 1265494179.720265 timer.c: Timer[ 3]: 1265494179.970265 timer.c: Timer[ 3]: 1265494180.220265 timer.c: Timer[ 3]: 1265494180.470265 timer.c: Timer[ 3]: 1265494180.720265 timer.c: Timer[ 3]: 1265494180.970265 timer.c: Timer[ 3]: 1265494181.220265 timer.c: Timer[ 3]: 1265494181.470265 timer.c: Timer[ 3]: 1265494181.720265 timer.c: Timer[ 3]: 1265494181.970265 timer.c: Timer[ 3]: 1265494182.220265 timer.c: Timer[ 3]: 1265494182.470265 timer.c: Timer[ 3]: 1265494182.720265 timer.c: Timer[ 3]: 1265494182.970265 timer.c: Timer[ 3]: 1265494183.220265 timer.c: Timer[ 3]: 1265494183.470265 timer.c: Timer[ 3]: 1265494183.720265 timer.c: Timer[ 3]: 1265494183.970265 timer.c: Timer[ 3]: 1265494184.220265 timer.c: Timer[ 3]: 1265494184.470265 timer.c: Timer[ 3]: 1265494184.720265 timer.c: Timer[ 3]: 1265494184.970265 timer.c: Timer[ 3]: 1265494185.220265 timer.c: Timer[ 3]: 1265494185.470265 timer.c: Timer[ 3]: 1265494185.720265 timer.c: Timer[ 3]: 1265494185.970265 timer.c: Timer[ 3]: 1265494186.220265 timer.c: Timer[ 3]: 1265494186.470265 timer.c: Timer[ 3]: 1265494186.720265 timer.c: Timer[ 3]: 1265494186.970265 timer.c: Timer[ 3]: 1265494187.220265 timer.c: Timer[ 3]: 1265494187.470265 timer.c: Timer[ 3]: 1265494187.720265 timer.c: Timer[ 4]: 1265494166.970307 timer.c: Timer[ 4]: 1265494167.220307 timer.c: Timer[ 4]: 1265494167.470307 timer.c: Timer[ 4]: 1265494167.720307 timer.c: Timer[ 4]: 1265494167.970307 timer.c: Timer[ 4]: 1265494168.220307 timer.c: Timer[ 4]: 1265494168.470307 timer.c: Timer[ 4]: 1265494168.720307 timer.c: Timer[ 4]: 1265494168.970307 timer.c: Timer[ 4]: 1265494169.220307 timer.c: Timer[ 4]: 1265494169.470307 timer.c: Timer[ 4]: 1265494169.720307 timer.c: Timer[ 4]: 1265494169.970307 timer.c: Timer[ 4]: 1265494170.220307 timer.c: Timer[ 4]: 1265494170.470307 timer.c: Timer[ 4]: 1265494170.720307 timer.c: Timer[ 4]: 1265494170.970307 timer.c: Timer[ 4]: 1265494171.220307 timer.c: Timer[ 4]: 1265494171.470307 timer.c: Timer[ 4]: 1265494171.720307 timer.c: Timer[ 4]: 1265494171.970307 timer.c: Timer[ 4]: 1265494172.220307 timer.c: Timer[ 4]: 1265494172.470307 timer.c: Timer[ 4]: 1265494172.720307 timer.c: Timer[ 4]: 1265494172.970307 timer.c: Timer[ 4]: 1265494173.220307 timer.c: Timer[ 4]: 1265494173.470307 timer.c: Timer[ 4]: 1265494173.720307 timer.c: Timer[ 4]: 1265494173.970307 timer.c: Timer[ 4]: 1265494174.220307 timer.c: Timer[ 4]: 1265494174.470307 timer.c: Timer[ 4]: 1265494174.720307 timer.c: Timer[ 4]: 1265494174.970307 timer.c: Timer[ 4]: 1265494175.220307 timer.c: Timer[ 4]: 1265494175.470307 timer.c: Timer[ 4]: 1265494175.720307 timer.c: Timer[ 4]: 1265494175.970307 timer.c: Timer[ 4]: 1265494176.220307 timer.c: Timer[ 4]: 1265494176.470307 timer.c: Timer[ 4]: 1265494176.720307 timer.c: Timer[ 4]: 1265494176.970307 timer.c: Timer[ 4]: 1265494177.220307 timer.c: Timer[ 4]: 1265494177.470307 timer.c: Timer[ 4]: 1265494177.720307 timer.c: Timer[ 4]: 1265494177.970307 timer.c: Timer[ 4]: 1265494178.220307 timer.c: Timer[ 4]: 1265494178.470307 timer.c: Timer[ 4]: 1265494178.720307 timer.c: Timer[ 4]: 1265494178.970307 timer.c: Timer[ 4]: 1265494179.220307 timer.c: Timer[ 4]: 1265494179.470307 timer.c: Timer[ 4]: 1265494179.720307 timer.c: Timer[ 4]: 1265494179.970307 timer.c: Timer[ 4]: 1265494180.220307 timer.c: Timer[ 4]: 1265494180.470307 timer.c: Timer[ 4]: 1265494180.720307 timer.c: Timer[ 4]: 1265494180.970307 timer.c: Timer[ 4]: 1265494181.220307 timer.c: Timer[ 4]: 1265494181.470307 timer.c: Timer[ 4]: 1265494181.720307 timer.c: Timer[ 4]: 1265494181.970307 timer.c: Timer[ 4]: 1265494182.220307 timer.c: Timer[ 4]: 1265494182.470307 timer.c: Timer[ 4]: 1265494182.720307 timer.c: Timer[ 4]: 1265494182.970307 timer.c: Timer[ 4]: 1265494183.220307 timer.c: Timer[ 4]: 1265494183.470307 timer.c: Timer[ 4]: 1265494183.720307 timer.c: Timer[ 4]: 1265494183.970307 timer.c: Timer[ 4]: 1265494184.220307 timer.c: Timer[ 4]: 1265494184.470307 timer.c: Timer[ 4]: 1265494184.720307 timer.c: Timer[ 4]: 1265494184.970307 timer.c: Timer[ 4]: 1265494185.220307 timer.c: Timer[ 4]: 1265494185.470307 timer.c: Timer[ 4]: 1265494185.720307 timer.c: Timer[ 4]: 1265494185.970307 timer.c: Timer[ 4]: 1265494186.220307 timer.c: Timer[ 4]: 1265494186.470307 timer.c: Timer[ 4]: 1265494186.720307 timer.c: Timer[ 4]: 1265494186.970307 timer.c: Timer[ 4]: 1265494187.220307 timer.c: Timer[ 4]: 1265494187.470307 timer.c: Timer[ 4]: 1265494187.720307 timer.c: Timer[ 5]: 1265494166.970349 timer.c: Timer[ 5]: 1265494167.220349 timer.c: Timer[ 5]: 1265494167.470349 timer.c: Timer[ 5]: 1265494167.720349 timer.c: Timer[ 5]: 1265494167.970349 timer.c: Timer[ 5]: 1265494168.220349 timer.c: Timer[ 5]: 1265494168.470349 timer.c: Timer[ 5]: 1265494168.720349 timer.c: Timer[ 5]: 1265494168.970349 timer.c: Timer[ 5]: 1265494169.220349 timer.c: Timer[ 5]: 1265494169.470349 timer.c: Timer[ 5]: 1265494169.720349 timer.c: Timer[ 5]: 1265494169.970349 timer.c: Timer[ 5]: 1265494170.220349 timer.c: Timer[ 5]: 1265494170.470349 timer.c: Timer[ 5]: 1265494170.720349 timer.c: Timer[ 5]: 1265494170.970349 timer.c: Timer[ 5]: 1265494171.220349 timer.c: Timer[ 5]: 1265494171.470349 timer.c: Timer[ 5]: 1265494171.720349 timer.c: Timer[ 5]: 1265494171.970349 timer.c: Timer[ 5]: 1265494172.220349 timer.c: Timer[ 5]: 1265494172.470349 timer.c: Timer[ 5]: 1265494172.720349 timer.c: Timer[ 5]: 1265494172.970349 timer.c: Timer[ 5]: 1265494173.220349 timer.c: Timer[ 5]: 1265494173.470349 timer.c: Timer[ 5]: 1265494173.720349 timer.c: Timer[ 5]: 1265494173.970349 timer.c: Timer[ 5]: 1265494174.220349 timer.c: Timer[ 5]: 1265494174.470349 timer.c: Timer[ 5]: 1265494174.720349 timer.c: Timer[ 5]: 1265494174.970349 timer.c: Timer[ 5]: 1265494175.220349 timer.c: Timer[ 5]: 1265494175.470349 timer.c: Timer[ 5]: 1265494175.720349 timer.c: Timer[ 5]: 1265494175.970349 timer.c: Timer[ 5]: 1265494176.220349 timer.c: Timer[ 5]: 1265494176.470349 timer.c: Timer[ 5]: 1265494176.720349 timer.c: Timer[ 5]: 1265494176.970349 timer.c: Timer[ 5]: 1265494177.220349 timer.c: Timer[ 5]: 1265494177.470349 timer.c: Timer[ 5]: 1265494177.720349 timer.c: Timer[ 5]: 1265494177.970349 timer.c: Timer[ 5]: 1265494178.220349 timer.c: Timer[ 5]: 1265494178.470349 timer.c: Timer[ 5]: 1265494178.720349 timer.c: Timer[ 5]: 1265494178.970349 timer.c: Timer[ 5]: 1265494179.220349 timer.c: Timer[ 5]: 1265494179.470349 timer.c: Timer[ 5]: 1265494179.720349 timer.c: Timer[ 5]: 1265494179.970349 timer.c: Timer[ 5]: 1265494180.220349 timer.c: Timer[ 5]: 1265494180.470349 timer.c: Timer[ 5]: 1265494180.720349 timer.c: Timer[ 5]: 1265494180.970349 timer.c: Timer[ 5]: 1265494181.220349 timer.c: Timer[ 5]: 1265494181.470349 timer.c: Timer[ 5]: 1265494181.720349 timer.c: Timer[ 5]: 1265494181.970349 timer.c: Timer[ 5]: 1265494182.220349 timer.c: Timer[ 5]: 1265494182.470349 timer.c: Timer[ 5]: 1265494182.720349 timer.c: Timer[ 5]: 1265494182.970349 timer.c: Timer[ 5]: 1265494183.220349 timer.c: Timer[ 5]: 1265494183.470349 timer.c: Timer[ 5]: 1265494183.720349 timer.c: Timer[ 5]: 1265494183.970349 timer.c: Timer[ 5]: 1265494184.220349 timer.c: Timer[ 5]: 1265494184.470349 timer.c: Timer[ 5]: 1265494184.720349 timer.c: Timer[ 5]: 1265494184.970349 timer.c: Timer[ 5]: 1265494185.220349 timer.c: Timer[ 5]: 1265494185.470349 timer.c: Timer[ 5]: 1265494185.720349 timer.c: Timer[ 5]: 1265494185.970349 timer.c: Timer[ 5]: 1265494186.220349 timer.c: Timer[ 5]: 1265494186.470349 timer.c: Timer[ 5]: 1265494186.720349 timer.c: Timer[ 5]: 1265494186.970349 timer.c: Timer[ 5]: 1265494187.220349 timer.c: Timer[ 5]: 1265494187.470349 timer.c: Timer[ 5]: 1265494187.720349 timer.c: Timer[ 6]: 1265494166.970390 timer.c: Timer[ 6]: 1265494167.220390 timer.c: Timer[ 6]: 1265494167.470390 timer.c: Timer[ 6]: 1265494167.720390 timer.c: Timer[ 6]: 1265494167.970390 timer.c: Timer[ 6]: 1265494168.220390 timer.c: Timer[ 6]: 1265494168.470390 timer.c: Timer[ 6]: 1265494168.720390 timer.c: Timer[ 6]: 1265494168.970390 timer.c: Timer[ 6]: 1265494169.220390 timer.c: Timer[ 6]: 1265494169.470390 timer.c: Timer[ 6]: 1265494169.720390 timer.c: Timer[ 6]: 1265494169.970390 timer.c: Timer[ 6]: 1265494170.220390 timer.c: Timer[ 6]: 1265494170.470390 timer.c: Timer[ 6]: 1265494170.720390 timer.c: Timer[ 6]: 1265494170.970390 timer.c: Timer[ 6]: 1265494171.220390 timer.c: Timer[ 6]: 1265494171.470390 timer.c: Timer[ 6]: 1265494171.720390 timer.c: Timer[ 6]: 1265494171.970390 timer.c: Timer[ 6]: 1265494172.220390 timer.c: Timer[ 6]: 1265494172.470390 timer.c: Timer[ 6]: 1265494172.720390 timer.c: Timer[ 6]: 1265494172.970390 timer.c: Timer[ 6]: 1265494173.220390 timer.c: Timer[ 6]: 1265494173.470390 timer.c: Timer[ 6]: 1265494173.720390 timer.c: Timer[ 6]: 1265494173.970390 timer.c: Timer[ 6]: 1265494174.220390 timer.c: Timer[ 6]: 1265494174.470390 timer.c: Timer[ 6]: 1265494174.720390 timer.c: Timer[ 6]: 1265494174.970390 timer.c: Timer[ 6]: 1265494175.220390 timer.c: Timer[ 6]: 1265494175.470390 timer.c: Timer[ 6]: 1265494175.720390 timer.c: Timer[ 6]: 1265494175.970390 timer.c: Timer[ 6]: 1265494176.220390 timer.c: Timer[ 6]: 1265494176.470390 timer.c: Timer[ 6]: 1265494176.720390 timer.c: Timer[ 6]: 1265494176.970390 timer.c: Timer[ 6]: 1265494177.220390 timer.c: Timer[ 6]: 1265494177.470390 timer.c: Timer[ 6]: 1265494177.720390 timer.c: Timer[ 6]: 1265494177.970390 timer.c: Timer[ 6]: 1265494178.220390 timer.c: Timer[ 6]: 1265494178.470390 timer.c: Timer[ 6]: 1265494178.720390 timer.c: Timer[ 6]: 1265494178.970390 timer.c: Timer[ 6]: 1265494179.220390 timer.c: Timer[ 6]: 1265494179.470390 timer.c: Timer[ 6]: 1265494179.720390 timer.c: Timer[ 6]: 1265494179.970390 timer.c: Timer[ 6]: 1265494180.220390 timer.c: Timer[ 6]: 1265494180.470390 timer.c: Timer[ 6]: 1265494180.720390 timer.c: Timer[ 6]: 1265494180.970390 timer.c: Timer[ 6]: 1265494181.220390 timer.c: Timer[ 6]: 1265494181.470390 timer.c: Timer[ 6]: 1265494181.720390 timer.c: Timer[ 6]: 1265494181.970390 timer.c: Timer[ 6]: 1265494182.220390 timer.c: Timer[ 6]: 1265494182.470390 timer.c: Timer[ 6]: 1265494182.720390 timer.c: Timer[ 6]: 1265494182.970390 timer.c: Timer[ 6]: 1265494183.220390 timer.c: Timer[ 6]: 1265494183.470390 timer.c: Timer[ 6]: 1265494183.720390 timer.c: Timer[ 6]: 1265494183.970390 timer.c: Timer[ 6]: 1265494184.220390 timer.c: Timer[ 6]: 1265494184.470390 timer.c: Timer[ 6]: 1265494184.720390 timer.c: Timer[ 6]: 1265494184.970390 timer.c: Timer[ 6]: 1265494185.220390 timer.c: Timer[ 6]: 1265494185.470390 timer.c: Timer[ 6]: 1265494185.720390 timer.c: Timer[ 6]: 1265494185.970390 timer.c: Timer[ 6]: 1265494186.220390 timer.c: Timer[ 6]: 1265494186.470390 timer.c: Timer[ 6]: 1265494186.720390 timer.c: Timer[ 6]: 1265494186.970390 timer.c: Timer[ 6]: 1265494187.220390 timer.c: Timer[ 6]: 1265494187.470390 timer.c: Timer[ 6]: 1265494187.720390 timer.c: Timer[ 7]: 1265494166.970435 timer.c: Timer[ 7]: 1265494167.220435 timer.c: Timer[ 7]: 1265494167.470435 timer.c: Timer[ 7]: 1265494167.720435 timer.c: Timer[ 7]: 1265494167.970435 timer.c: Timer[ 7]: 1265494168.220435 timer.c: Timer[ 7]: 1265494168.470435 timer.c: Timer[ 7]: 1265494168.720435 timer.c: Timer[ 7]: 1265494168.970435 timer.c: Timer[ 7]: 1265494169.220435 timer.c: Timer[ 7]: 1265494169.470435 timer.c: Timer[ 7]: 1265494169.720435 timer.c: Timer[ 7]: 1265494169.970435 timer.c: Timer[ 7]: 1265494170.220435 timer.c: Timer[ 7]: 1265494170.470435 timer.c: Timer[ 7]: 1265494170.720435 timer.c: Timer[ 7]: 1265494170.970435 timer.c: Timer[ 7]: 1265494171.220435 timer.c: Timer[ 7]: 1265494171.470435 timer.c: Timer[ 7]: 1265494171.720435 timer.c: Timer[ 7]: 1265494171.970435 timer.c: Timer[ 7]: 1265494172.220435 timer.c: Timer[ 7]: 1265494172.470435 timer.c: Timer[ 7]: 1265494172.720435 timer.c: Timer[ 7]: 1265494172.970435 timer.c: Timer[ 7]: 1265494173.220435 timer.c: Timer[ 7]: 1265494173.470435 timer.c: Timer[ 7]: 1265494173.720435 timer.c: Timer[ 7]: 1265494173.970435 timer.c: Timer[ 7]: 1265494174.220435 timer.c: Timer[ 7]: 1265494174.470435 timer.c: Timer[ 7]: 1265494174.720435 timer.c: Timer[ 7]: 1265494174.970435 timer.c: Timer[ 7]: 1265494175.220435 timer.c: Timer[ 7]: 1265494175.470435 timer.c: Timer[ 7]: 1265494175.720435 timer.c: Timer[ 7]: 1265494175.970435 timer.c: Timer[ 7]: 1265494176.220435 timer.c: Timer[ 7]: 1265494176.470435 timer.c: Timer[ 7]: 1265494176.720435 timer.c: Timer[ 7]: 1265494176.970435 timer.c: Timer[ 7]: 1265494177.220435 timer.c: Timer[ 7]: 1265494177.470435 timer.c: Timer[ 7]: 1265494177.720435 timer.c: Timer[ 7]: 1265494177.970435 timer.c: Timer[ 7]: 1265494178.220435 timer.c: Timer[ 7]: 1265494178.470435 timer.c: Timer[ 7]: 1265494178.720435 timer.c: Timer[ 7]: 1265494178.970435 timer.c: Timer[ 7]: 1265494179.220435 timer.c: Timer[ 7]: 1265494179.470435 timer.c: Timer[ 7]: 1265494179.720435 timer.c: Timer[ 7]: 1265494179.970435 timer.c: Timer[ 7]: 1265494180.220435 timer.c: Timer[ 7]: 1265494180.470435 timer.c: Timer[ 7]: 1265494180.720435 timer.c: Timer[ 7]: 1265494180.970435 timer.c: Timer[ 7]: 1265494181.220435 timer.c: Timer[ 7]: 1265494181.470435 timer.c: Timer[ 7]: 1265494181.720435 timer.c: Timer[ 7]: 1265494181.970435 timer.c: Timer[ 7]: 1265494182.220435 timer.c: Timer[ 7]: 1265494182.470435 timer.c: Timer[ 7]: 1265494182.720435 timer.c: Timer[ 7]: 1265494182.970435 timer.c: Timer[ 7]: 1265494183.220435 timer.c: Timer[ 7]: 1265494183.470435 timer.c: Timer[ 7]: 1265494183.720435 timer.c: Timer[ 7]: 1265494183.970435 timer.c: Timer[ 7]: 1265494184.220435 timer.c: Timer[ 7]: 1265494184.470435 timer.c: Timer[ 7]: 1265494184.720435 timer.c: Timer[ 7]: 1265494184.970435 timer.c: Timer[ 7]: 1265494185.220435 timer.c: Timer[ 7]: 1265494185.470435 timer.c: Timer[ 7]: 1265494185.720435 timer.c: Timer[ 7]: 1265494185.970435 timer.c: Timer[ 7]: 1265494186.220435 timer.c: Timer[ 7]: 1265494186.470435 timer.c: Timer[ 7]: 1265494186.720435 timer.c: Timer[ 7]: 1265494186.970435 timer.c: Timer[ 7]: 1265494187.220435 timer.c: Timer[ 7]: 1265494187.470435 timer.c: Timer[ 7]: 1265494187.720435 timer.c: Timer[ 8]: 1265494166.970481 timer.c: Timer[ 8]: 1265494167.220481 timer.c: Timer[ 8]: 1265494167.470481 timer.c: Timer[ 8]: 1265494167.720481 timer.c: Timer[ 8]: 1265494167.970481 timer.c: Timer[ 8]: 1265494168.220481 timer.c: Timer[ 8]: 1265494168.470481 timer.c: Timer[ 8]: 1265494168.720481 timer.c: Timer[ 8]: 1265494168.970481 timer.c: Timer[ 8]: 1265494169.220481 timer.c: Timer[ 8]: 1265494169.470481 timer.c: Timer[ 8]: 1265494169.720481 timer.c: Timer[ 8]: 1265494169.970481 timer.c: Timer[ 8]: 1265494170.220481 timer.c: Timer[ 8]: 1265494170.470481 timer.c: Timer[ 8]: 1265494170.720481 timer.c: Timer[ 8]: 1265494170.970481 timer.c: Timer[ 8]: 1265494171.220481 timer.c: Timer[ 8]: 1265494171.470481 timer.c: Timer[ 8]: 1265494171.720481 timer.c: Timer[ 8]: 1265494171.970481 timer.c: Timer[ 8]: 1265494172.220481 timer.c: Timer[ 8]: 1265494172.470481 timer.c: Timer[ 8]: 1265494172.720481 timer.c: Timer[ 8]: 1265494172.970481 timer.c: Timer[ 8]: 1265494173.220481 timer.c: Timer[ 8]: 1265494173.470481 timer.c: Timer[ 8]: 1265494173.720481 timer.c: Timer[ 8]: 1265494173.970481 timer.c: Timer[ 8]: 1265494174.220481 timer.c: Timer[ 8]: 1265494174.470481 timer.c: Timer[ 8]: 1265494174.720481 timer.c: Timer[ 8]: 1265494174.970481 timer.c: Timer[ 8]: 1265494175.220481 timer.c: Timer[ 8]: 1265494175.470481 timer.c: Timer[ 8]: 1265494175.720481 timer.c: Timer[ 8]: 1265494175.970481 timer.c: Timer[ 8]: 1265494176.220481 timer.c: Timer[ 8]: 1265494176.470481 timer.c: Timer[ 8]: 1265494176.720481 timer.c: Timer[ 8]: 1265494176.970481 timer.c: Timer[ 8]: 1265494177.220481 timer.c: Timer[ 8]: 1265494177.470481 timer.c: Timer[ 8]: 1265494177.720481 timer.c: Timer[ 8]: 1265494177.970481 timer.c: Timer[ 8]: 1265494178.220481 timer.c: Timer[ 8]: 1265494178.470481 timer.c: Timer[ 8]: 1265494178.720481 timer.c: Timer[ 8]: 1265494178.970481 timer.c: Timer[ 8]: 1265494179.220481 timer.c: Timer[ 8]: 1265494179.470481 timer.c: Timer[ 8]: 1265494179.720481 timer.c: Timer[ 8]: 1265494179.970481 timer.c: Timer[ 8]: 1265494180.220481 timer.c: Timer[ 8]: 1265494180.470481 timer.c: Timer[ 8]: 1265494180.720481 timer.c: Timer[ 8]: 1265494180.970481 timer.c: Timer[ 8]: 1265494181.220481 timer.c: Timer[ 8]: 1265494181.470481 timer.c: Timer[ 8]: 1265494181.720481 timer.c: Timer[ 8]: 1265494181.970481 timer.c: Timer[ 8]: 1265494182.220481 timer.c: Timer[ 8]: 1265494182.470481 timer.c: Timer[ 8]: 1265494182.720481 timer.c: Timer[ 8]: 1265494182.970481 timer.c: Timer[ 8]: 1265494183.220481 timer.c: Timer[ 8]: 1265494183.470481 timer.c: Timer[ 8]: 1265494183.720481 timer.c: Timer[ 8]: 1265494183.970481 timer.c: Timer[ 8]: 1265494184.220481 timer.c: Timer[ 8]: 1265494184.470481 timer.c: Timer[ 8]: 1265494184.720481 timer.c: Timer[ 8]: 1265494184.970481 timer.c: Timer[ 8]: 1265494185.220481 timer.c: Timer[ 8]: 1265494185.470481 timer.c: Timer[ 8]: 1265494185.720481 timer.c: Timer[ 8]: 1265494185.970481 timer.c: Timer[ 8]: 1265494186.220481 timer.c: Timer[ 8]: 1265494186.470481 timer.c: Timer[ 8]: 1265494186.720481 timer.c: Timer[ 8]: 1265494186.970481 timer.c: Timer[ 8]: 1265494187.220481 timer.c: Timer[ 8]: 1265494187.470481 timer.c: Timer[ 8]: 1265494187.720481 timer.c: Timer[ 9]: 1265494166.970578 timer.c: Timer[ 9]: 1265494167.220578 timer.c: Timer[ 9]: 1265494167.470578 timer.c: Timer[ 9]: 1265494167.720578 timer.c: Timer[ 9]: 1265494167.970578 timer.c: Timer[ 9]: 1265494168.220578 timer.c: Timer[ 9]: 1265494168.470578 timer.c: Timer[ 9]: 1265494168.720578 timer.c: Timer[ 9]: 1265494168.970578 timer.c: Timer[ 9]: 1265494169.220578 timer.c: Timer[ 9]: 1265494169.470578 timer.c: Timer[ 9]: 1265494169.720578 timer.c: Timer[ 9]: 1265494169.970578 timer.c: Timer[ 9]: 1265494170.220578 timer.c: Timer[ 9]: 1265494170.470578 timer.c: Timer[ 9]: 1265494170.720578 timer.c: Timer[ 9]: 1265494170.970578 timer.c: Timer[ 9]: 1265494171.220578 timer.c: Timer[ 9]: 1265494171.470578 timer.c: Timer[ 9]: 1265494171.720578 timer.c: Timer[ 9]: 1265494171.970578 timer.c: Timer[ 9]: 1265494172.220578 timer.c: Timer[ 9]: 1265494172.470578 timer.c: Timer[ 9]: 1265494172.720578 timer.c: Timer[ 9]: 1265494172.970578 timer.c: Timer[ 9]: 1265494173.220578 timer.c: Timer[ 9]: 1265494173.470578 timer.c: Timer[ 9]: 1265494173.720578 timer.c: Timer[ 9]: 1265494173.970578 timer.c: Timer[ 9]: 1265494174.220578 timer.c: Timer[ 9]: 1265494174.470578 timer.c: Timer[ 9]: 1265494174.720578 timer.c: Timer[ 9]: 1265494174.970578 timer.c: Timer[ 9]: 1265494175.220578 timer.c: Timer[ 9]: 1265494175.470578 timer.c: Timer[ 9]: 1265494175.720578 timer.c: Timer[ 9]: 1265494175.970578 timer.c: Timer[ 9]: 1265494176.220578 timer.c: Timer[ 9]: 1265494176.470578 timer.c: Timer[ 9]: 1265494176.720578 timer.c: Timer[ 9]: 1265494176.970578 timer.c: Timer[ 9]: 1265494177.220578 timer.c: Timer[ 9]: 1265494177.470578 timer.c: Timer[ 9]: 1265494177.720578 timer.c: Timer[ 9]: 1265494177.970578 timer.c: Timer[ 9]: 1265494178.220578 timer.c: Timer[ 9]: 1265494178.470578 timer.c: Timer[ 9]: 1265494178.720578 timer.c: Timer[ 9]: 1265494178.970578 timer.c: Timer[ 9]: 1265494179.220578 timer.c: Timer[ 9]: 1265494179.470578 timer.c: Timer[ 9]: 1265494179.720578 timer.c: Timer[ 9]: 1265494179.970578 timer.c: Timer[ 9]: 1265494180.220578 timer.c: Timer[ 9]: 1265494180.470578 timer.c: Timer[ 9]: 1265494180.720578 timer.c: Timer[ 9]: 1265494180.970578 timer.c: Timer[ 9]: 1265494181.220578 timer.c: Timer[ 9]: 1265494181.470578 timer.c: Timer[ 9]: 1265494181.720578 timer.c: Timer[ 9]: 1265494181.970578 timer.c: Timer[ 9]: 1265494182.220578 timer.c: Timer[ 9]: 1265494182.470578 timer.c: Timer[ 9]: 1265494182.720578 timer.c: Timer[ 9]: 1265494182.970578 timer.c: Timer[ 9]: 1265494183.220578 timer.c: Timer[ 9]: 1265494183.470578 timer.c: Timer[ 9]: 1265494183.720578 timer.c: Timer[ 9]: 1265494183.970578 timer.c: Timer[ 9]: 1265494184.220578 timer.c: Timer[ 9]: 1265494184.470578 timer.c: Timer[ 9]: 1265494184.720578 timer.c: Timer[ 9]: 1265494184.970578 timer.c: Timer[ 9]: 1265494185.220578 timer.c: Timer[ 9]: 1265494185.470578 timer.c: Timer[ 9]: 1265494185.720578 timer.c: Timer[ 9]: 1265494185.970578 timer.c: Timer[ 9]: 1265494186.220578 timer.c: Timer[ 9]: 1265494186.470578 timer.c: Timer[ 9]: 1265494186.720578 timer.c: Timer[ 9]: 1265494186.970578 timer.c: Timer[ 9]: 1265494187.220578 timer.c: Timer[ 9]: 1265494187.470578 timer.c: Timer[ 9]: 1265494187.720578 May I draw your attention to the last digits? And no, this is not faked... :) I repeat my old question: shall I commit, or shan't I commit? ;) Best regards, Martin -- www.mzuther.de www.radix-musik.de |
From: Martin Z. <co...@mz...> - 2010-02-06 21:20:26
|
Dear Michael! > I hope you all do understand what I'm talking about.... To be honest, I don't... :) First, I think we have to define the problem, because in my opinion there are two of them that need separate solving. One is the time-shift that is introduced by processing. The other one is that of unsynchronised widgets, and I have already solved that, at least partially. So let's talk about time-shifts. On looking through the code again, I think I have pinpointed the problem. First, using one-shot timers for widgets doesn't seem to make sense to me. First, there is the overhead of deleting the old one and creating a new one. Second, most (if not all) widgets are triggered regularly, so using one-shot timers isn't the best solution. If this was changed (I have temporally done this for "widget_icon.c" while so far ignoring the problem of timer deletion or widget deletion), we can now move on to "timer.c". First, have a look at line 182, which is where a single *continuous* timer is being respawned: } else { Timers[i].when = now; timer_inc(&Timers[i].when, Timers[i].interval); } I think the second line (which sets the timer to "now") is plain wrong because it automatically delays a timer by the time the callback needs for processing. So this line should be removed as fast as possible! Another, albeit smaller, problem lies in line 206: /* delay until next timer event */ struct timeval diff; timersub(&Timers[min].when, &now, &diff); delay->tv_sec = diff.tv_sec; /* microseconds to nanoseconds!! */ delay->tv_nsec = diff.tv_usec * 1000; Here, the delay to the next timer event is too long, because we ignore the processing time between reading the value for "now" and calculating the delay. What we need here is to update the value for "now" and only then calculate the delay: /* delay until next timer event */ struct timeval diff; timersub(&Timers[min].when, &now, &diff); gettimeofday(&now, NULL); [...] Now for a real time test: one single icon widget with update set to 1000 ms. I have also removed the timers with id 0, as they are used for updating the X11 driver. They do, however, behave just as the other timers. Before the changes mentioned above (continuous timers and the two code sections): Timers[ 1]: 1265490676.166966 Timers[ 2]: 1265490677.167110 Timers[ 1]: 1265490678.167248 Timers[ 2]: 1265490679.167385 Timers[ 1]: 1265490680.167532 Timers[ 2]: 1265490681.167672 Timers[ 1]: 1265490682.167822 Timers[ 2]: 1265490683.167960 Timers[ 1]: 1265490684.168108 Timers[ 2]: 1265490685.168249 Timers[ 1]: 1265490686.168387 Timers[ 2]: 1265490687.168525 Timers[ 1]: 1265490688.168652 Timers[ 2]: 1265490689.168780 Timers[ 1]: 1265490690.168908 After 15 seconds (and therefore 15 updates), we have a time-shift of 1.9 ms. Just for one single widget! After applying the changes: Timers[ 1]: 1265490514.609078 Timers[ 1]: 1265490515.609079 Timers[ 1]: 1265490516.609078 Timers[ 1]: 1265490517.609078 Timers[ 1]: 1265490518.609079 Timers[ 1]: 1265490519.609078 Timers[ 1]: 1265490520.609076 Timers[ 1]: 1265490521.609079 Timers[ 1]: 1265490522.609078 Timers[ 1]: 1265490523.609079 Timers[ 1]: 1265490524.609079 Timers[ 1]: 1265490525.609079 Timers[ 1]: 1265490526.609078 Timers[ 1]: 1265490527.609094 <-- glitch Timers[ 1]: 1265490528.609078 Here we only have a time-shift of only 1 *microsecond*! Also note that the "glitch" is recovered later on. So it seems that we don't need any "processing magic" at all. Just convert the widgets to continuous timers and make the two changes in "timer.c", and we're set! Actually, I didn't think it was *that* easy, and maybe I have overseen something -- but maybe that's just it! :) Have a nice week-end, Martin -- www.mzuther.de www.radix-musik.de |
From: Martin Z. <co...@mz...> - 2010-02-06 11:34:19
|
Hi Michael, I have now changed the code in "timer.c" to use the functions timeradd() and timersub(). Even though it may expand to the same code, I think it makes for cleaner code. And if we *want* to think about improving the timer functionality, clean code definitely helps. :) Bye, Martin -- www.mzuther.de www.radix-musik.de |
From: Michael R. <mi...@re...> - 2010-02-04 15:16:58
|
Hi Martin, > I think you have gotten me wrong. The timers run pretty fine. The > problem is that each widget has its own timer with its own starting > time, so the widgets aren't synchronised to begin with. Ok, thanks for your explanation, now I got you! BUT (you know, there's alwys a BUT from my side ;-) I know this "timers getting out of sync" problem for years, never had the time to dig into that. While your modification surely solves this for widget updates, I want to get rid of it fundamentally. Apart from that, one (future) extension would be impossible: think of two widgets, both having an update timer of say 500 msec, but the second one is being pre-delayed by 250 msec (there is no such thing like a initial delay at the moment, but you never can tell with the future..) I think a clean solution would be to re-sync the timers. Given the fact that there should be no timer less that 10 msec, and that computers are fast these days, there shouldn't be a difference of mor than 1 or 2 msec. But they sum up with the current code. My idea would be to process not only the timer(s) that expired *now* but also timers that expire at now+5 msec, and set the "last time fired" timestamp for all these timers to *now*. the last point should be already in there: the timer_process() gets the current timestamp only once, at the very beginning. So "slow" callbacks would not affect the timing. Another needed functionality is already inside: the loop not only looks for timers that expire *now*, but also for timers that expired in the past. I can think of several possible solutions: a) when looking for expired timers, look a short period time into the future b) call timer_process() not exactly at the timeout of the next timer, but a bit later, so more timers would have expired. c) do some rounding of timeout values, probably depending on the delay timne (e.g. 10% of delay time) especially c) sounds interesting to me: if a timer has a timeout of 200 msec, round the next start time to 20msec, so it expires at 0:0200, 0:0400, 0:0600, .... I hope you all do understand what I'm talking about.... bye, Michael -- Michael Reinelt <mi...@re...> http://home.pages.at/reinelt GPG-Key 0xDF13BA50 ICQ #288386781 |
From: Mattia Jona-L. <mat...@gm...> - 2010-02-04 14:42:30
|
Hi Michael, I tried my solution but it does not solve completely the problem. I'm working on it and when I find an elegant solution, I will commit it. For the moment let's keep the errno = 0 patch. Bye, Mattia On Thu, Feb 4, 2010 at 3:31 PM, Michael Reinelt <mi...@re...> wrote: > Hi Mattia, > > thanks a bunch for pointing this out! I didn't read the code that careful (fortunately you did!), but I'm afraid even if > I did I would have missed this... > > as you already provided a clean solution, could you please check it in? > > > > TIA, Michael > > Mattia Jona-Lasinio schrieb: >> Hi Claas, Michael and The List! >> >> IMHO explicitely clearing the errno variable is generally a _VEEEEERY_ >> bad idea and should never be done. >> errno should be treated like a read only variable that one must assume >> to be completely undefined before a function that is allowed to modify >> it, is actually called. This means that its value must not be checked >> before calling the function that might change it, is actually called. >> And in any case the errno value must be checked only after checking >> the return value of the called function. >> Unfortunately in plugin_fifo.c, line 191 >> >> while (bytes > 0 && errno != EINTR) { >> bytes = read(fd.input, buf, FIFO_BUFFER_SIZE); >> } >> >> the value of errno is checked BEFORE the very first call to read. Then >> a previous function call might had set its value to EINTR and we are >> not going to read anything just because errno was spuriously set. In >> any case this piece of code is buggy because errno is set by read only >> if bytes < 0 OR 0 <= bytes < FIFO_BUFFER_SIZE, but is untouched >> (therefore still undefined) if bytes == FIFO_BUFFER_SIZE. >> >> But the solution is not clearing errno, but rather changing the code >> above to fix this bug. Something like >> >> while ((bytes = read(fd.input, buf, FIFO_BUFFER_SIZE)) > 0) { >> if (bytes < FIFO_BUFFER_SIZE && errno == EINTR) >> break; >> } >> >> so that the bytes = 1 initialization is not necessary. >> >> At this point the subsequent test >> >> if (bytes < 0 || (errno > 0 && errno != EAGAIN)) { >> error("[FIFO] Error %i: %s", errno, strerror(errno)); >> } >> >> becomes meaningful but one has to distinguish the cases "bytes < 0" >> (read returned an error) from "bytes < FIFO_BUFFER_SIZE" (there was >> just a "short" read), so that it should be something like >> >> if (bytes < 0 || (bytes < FIFO_BUFFER_SIZE && errno > 0 && errno != EAGAIN)) { >> error("[FIFO] Error %i: %s", errno, strerror(errno)); >> } >> >> >> What do you think about all this? >> >> >> Bye! >> >> >> Mattia >> >> >> >> On Thu, Feb 4, 2010 at 10:38 AM, Michael Reinelt <mi...@re...> wrote: >>> Applied! Thanks! >>> >>> Claas Hilbrecht schrieb: >>>> Hello, >>>> >>>> here is a very small fix (against current svn) for the plugin_fifo. You >>>> need to clear errno after creating the FIFO. Without clearing the errno >>>> variable you will get an error in fiforead() like this: >>>> >>>> [FIFO] Error 2: No such file or directory >>>> >>>> >>>> babel@eisler:~/tmp/lcd4linux$ svn diff plugin_fifo.c >>>> Index: plugin_fifo.c >>>> =================================================================== >>>> --- plugin_fifo.c (Revision 1097) >>>> +++ plugin_fifo.c (Arbeitskopie) >>>> @@ -110,6 +110,8 @@ >>>> error("Couldn't create FIFO \"%s\": %s\n", fd.path, >>>> strerror(errno)); >>>> return -1; >>>> } >>>> + /* clear errno */ >>>> + errno = 0; >>>> fd.created = 1; >>>> return 0; >>>> } >>>> >>>> Mit freundlichem Gruss >>>> Claas Hilbrecht >>>> >>>> >>>> ------------------------------------------------------------------------------ >>>> The Planet: dedicated and managed hosting, cloud storage, colocation >>>> Stay online with enterprise data centers and the best network in the business >>>> Choose flexible plans and management services without long-term contracts >>>> Personal 24x7 support from experience hosting pros just a phone call away. >>>> http://p.sf.net/sfu/theplanet-com >>>> _______________________________________________ >>>> Lcd4linux-devel mailing list >>>> Lcd...@li... >>>> https://lists.sourceforge.net/lists/listinfo/lcd4linux-devel >>>> >>>> >>> -- >>> Michael Reinelt <mi...@re...> >>> http://home.pages.at/reinelt >>> GPG-Key 0xDF13BA50 >>> ICQ #288386781 >>> >>> ------------------------------------------------------------------------------ >>> The Planet: dedicated and managed hosting, cloud storage, colocation >>> Stay online with enterprise data centers and the best network in the business >>> Choose flexible plans and management services without long-term contracts >>> Personal 24x7 support from experience hosting pros just a phone call away. >>> http://p.sf.net/sfu/theplanet-com >>> _______________________________________________ >>> Lcd4linux-devel mailing list >>> Lcd...@li... >>> https://lists.sourceforge.net/lists/listinfo/lcd4linux-devel >>> >> >> ------------------------------------------------------------------------------ >> The Planet: dedicated and managed hosting, cloud storage, colocation >> Stay online with enterprise data centers and the best network in the business >> Choose flexible plans and management services without long-term contracts >> Personal 24x7 support from experience hosting pros just a phone call away. >> http://p.sf.net/sfu/theplanet-com >> _______________________________________________ >> Lcd4linux-devel mailing list >> Lcd...@li... >> https://lists.sourceforge.net/lists/listinfo/lcd4linux-devel >> >> > > -- > Michael Reinelt <mi...@re...> > http://home.pages.at/reinelt > GPG-Key 0xDF13BA50 > ICQ #288386781 > |