Re: Running a script every second

2014-03-06 Thread Rich Felker
On Thu, Mar 06, 2014 at 02:34:25PM -0500, Michael Conrad wrote:
> I know this borders on bike-shedding, but if you really want to run
> something exactly 60 times per elapsed minute you need to compare
> calls to clock_gettime(CLOCK_MONOTONIC).  Nothing else will work
> reliably in all cases, and certainly not signals.  (if the system is
> lagged significantly, two signals can be merged into one)

POSIX timers with signal-based delivery can be used reliably for this
purpose too. Realtime signals can be queued, and even if the queue
overflows, the timer_getoverrun() function can tell you how many
overruns there were (so you can compensate).

In principle POSIX timers with thread-based delivery should also work
for this purpose, but due to bugs in glibc, it's not 100% reliable and
expirations may be lost. And if you don't mind using threads, it's
easy to just roll your own approach with clock_gettime and
clock_nanosleep with TIMER_ABSTIME, as you described.

Rich
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


Re: Running a script every second

2014-03-06 Thread Mike Dean
Or, you could use a Xenomai-enabled Linux kernel.  That way, Linux
*is* realtime,
so you will be guaranteed to get scheduled for execution every second.


Mike Dean

md...@emacinc.com
http://www.emacinc.com/

Engineer
EMAC, Inc.
618-529-4525 Ext. 330
618-457-0110 Fax
2390 EMAC Way
Carbondale, Il 62901



On Thu, Mar 6, 2014 at 1:34 PM, Michael Conrad wrote:

> I know this borders on bike-shedding, but if you really want to run
> something exactly 60 times per elapsed minute you need to compare calls to
> clock_gettime(CLOCK_MONOTONIC).  Nothing else will work reliably in all
> cases, and certainly not signals.  (if the system is lagged significantly,
> two signals can be merged into one)
>
> I'm not aware of any way to call clock_gettime from a shell script, but
> Perl can do it.  If you don't have perl and you still want it to be a
> script for ease-of-maintenance, I would recommend:
>
>   1. write a very small C program that calls clock_gettime() for an
> initial timestamp, writes "\n" on STDOUT, increment timestamp by exactly 1
> second, calls clock_gettime(), and then usleep()s for the difference
> between clock_gettime and timestamp, if greater than 0.
>
>   2. write a script that performs "./c_prog | while read; do something();
> done"
>
> No special file descriptors, process IDs, signals or other mess, and
> guaranteed one iteration of the script per every elapsed second (but no
> guarantee that the execution occurs during that second.  Linux isn't
> realtime, afterall)
>
> -Mike
>
>
> On 3/6/2014 9:25 AM, Yan Seiner wrote:
>
>>
>> On 03/05/2014 10:49 PM, Harald Becker wrote:
>>
>>> Hi Yan !
>>>
>>> On 05-03-2014 09:14 Yan Seiner  wrote:
>>>
 I am trying to run a script every second.

>>> Beside what Laurent told about using sleep, etc.
>>>
>>>  first script (the one that does the work)

 trap 'update' HUP
 mknod /tmp/dummyfifo p
 while true; do
  read < /tmp/dummyfifo > /dev/null 2>&1
 done
 The problem is that the 'read' generates a
 /usr/bin/update: line 1: can't open /tmp/dummyfifo: Interrupted
 system call

>>> The reason for this is you create your pipe once, but open it
>>> again at every iteration of the loop.
>>>
>>> Try the following:
>>>
>>> mknod /tmp/dummyfifo p
>>> exec 0/dev/null 2>&1
>>> while true; do
>>> read
>>> done
>>>
>>> This opens the fifo once and assigns it for stdin. After that it
>>> stays open until the first script is terminated in any way.
>>>
>>> In addition stdout *AND* stderr are redirected to /dev/null for
>>> all following commands in the script, so you need to redirect to
>>> any file or tty when you want do display something.
>>>
>>
>> Thanks!
>>
>> I like it.  My solution leaves 'cat' processes behind if the script gets
>> killed.  Usually not a problem since it's only invoked at boot.
>>
>> ___
>> busybox mailing list
>> busybox@busybox.net
>> http://lists.busybox.net/mailman/listinfo/busybox
>>
>
> ___
> busybox mailing list
> busybox@busybox.net
> http://lists.busybox.net/mailman/listinfo/busybox
>
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox

Re: Running a script every second

2014-03-06 Thread Michael Conrad
I know this borders on bike-shedding, but if you really want to run 
something exactly 60 times per elapsed minute you need to compare calls 
to clock_gettime(CLOCK_MONOTONIC).  Nothing else will work reliably in 
all cases, and certainly not signals.  (if the system is lagged 
significantly, two signals can be merged into one)


I'm not aware of any way to call clock_gettime from a shell script, but 
Perl can do it.  If you don't have perl and you still want it to be a 
script for ease-of-maintenance, I would recommend:


  1. write a very small C program that calls clock_gettime() for an 
initial timestamp, writes "\n" on STDOUT, increment timestamp by exactly 
1 second, calls clock_gettime(), and then usleep()s for the difference 
between clock_gettime and timestamp, if greater than 0.


  2. write a script that performs "./c_prog | while read; do 
something(); done"


No special file descriptors, process IDs, signals or other mess, and 
guaranteed one iteration of the script per every elapsed second (but no 
guarantee that the execution occurs during that second.  Linux isn't 
realtime, afterall)


-Mike

On 3/6/2014 9:25 AM, Yan Seiner wrote:


On 03/05/2014 10:49 PM, Harald Becker wrote:

Hi Yan !

On 05-03-2014 09:14 Yan Seiner  wrote:

I am trying to run a script every second.

Beside what Laurent told about using sleep, etc.


first script (the one that does the work)

trap 'update' HUP
mknod /tmp/dummyfifo p
while true; do
 read < /tmp/dummyfifo > /dev/null 2>&1
done
The problem is that the 'read' generates a
/usr/bin/update: line 1: can't open /tmp/dummyfifo: Interrupted
system call

The reason for this is you create your pipe once, but open it
again at every iteration of the loop.

Try the following:

mknod /tmp/dummyfifo p
exec 0/dev/null 2>&1
while true; do
read
done

This opens the fifo once and assigns it for stdin. After that it
stays open until the first script is terminated in any way.

In addition stdout *AND* stderr are redirected to /dev/null for
all following commands in the script, so you need to redirect to
any file or tty when you want do display something.


Thanks!

I like it.  My solution leaves 'cat' processes behind if the script 
gets killed.  Usually not a problem since it's only invoked at boot.


___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


[PATCH 2/2] shuf: small usage text consistency fix

2014-03-06 Thread Bartosz Golaszewski
Signed-off-by: Bartosz Golaszewski 
---
 coreutils/shuf.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/coreutils/shuf.c b/coreutils/shuf.c
index eff0d36..612b30e 100644
--- a/coreutils/shuf.c
+++ b/coreutils/shuf.c
@@ -17,13 +17,13 @@
 //applet:IF_SHUF(APPLET_NOEXEC(shuf, shuf, BB_DIR_USR_BIN, BB_SUID_DROP, shuf))
 
 //usage:#define shuf_trivial_usage
-//usage:   "[-e|-i LO-HI] [-n NUM] [-o FILE] [-z] [FILE|ARG...]"
+//usage:   "[-e|-i L-H] [-n NUM] [-o FILE] [-z] [FILE|ARG...]"
 //usage:#define shuf_full_usage "\n\n"
 //usage:   "Write a random permutation of the input lines to standard 
output\n"
 //usage: "\n   -e  Treat each ARG as an input line"
 //usage: "\n   -i L-H  Treat each number L through H as an input line"
 //usage: "\n   -n NUM  Output at most NUM lines"
-//usage: "\n   -o  Write result to FILE instead of standard output"
+//usage: "\n   -o FILE Write result to FILE instead of standard output"
 //usage: "\n   -z  End lines with zero byte, not newline"
 
 #include "libbb.h"
-- 
1.8.4.5

___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


[PATCH 1/2] shuf: fix a segfault on 'shuf -e'

2014-03-06 Thread Bartosz Golaszewski
Signed-off-by: Bartosz Golaszewski 
---
 coreutils/shuf.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/coreutils/shuf.c b/coreutils/shuf.c
index f213d67..eff0d36 100644
--- a/coreutils/shuf.c
+++ b/coreutils/shuf.c
@@ -126,7 +126,9 @@ int shuf_main(int argc, char **argv)
fclose_if_not_stdin(fp);
}
 
-   shuffle_lines(lines, numlines);
+   /* Skip shuffle_lines() for one or zero lines. */
+   if (numlines > 1)
+   shuffle_lines(lines, numlines);
 
if (opts & OPT_o)
xmove_fd(xopen(opt_o_str, O_WRONLY|O_CREAT|O_TRUNC), 
STDOUT_FILENO);
-- 
1.8.4.5

___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


Re: Running a script every second

2014-03-06 Thread Yan Seiner


On 03/05/2014 10:49 PM, Harald Becker wrote:

Hi Yan !

On 05-03-2014 09:14 Yan Seiner  wrote:

I am trying to run a script every second.

Beside what Laurent told about using sleep, etc.


first script (the one that does the work)

trap 'update' HUP
mknod /tmp/dummyfifo p
while true; do
 read < /tmp/dummyfifo > /dev/null 2>&1
done
The problem is that the 'read' generates a
/usr/bin/update: line 1: can't open /tmp/dummyfifo: Interrupted
system call

The reason for this is you create your pipe once, but open it
again at every iteration of the loop.

Try the following:

mknod /tmp/dummyfifo p
exec 0/dev/null 2>&1
while true; do
read
done

This opens the fifo once and assigns it for stdin. After that it
stays open until the first script is terminated in any way.

In addition stdout *AND* stderr are redirected to /dev/null for
all following commands in the script, so you need to redirect to
any file or tty when you want do display something.


Thanks!

I like it.  My solution leaves 'cat' processes behind if the script gets 
killed.  Usually not a problem since it's only invoked at boot.


___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


Re: Running a script every second

2014-03-06 Thread Yan Seiner


On 03/05/2014 10:07 AM, Laurent Bercot wrote:

On 2014-03-05 17:40, Yan Seiner wrote:

I am trying to run a script every second.  I set up two scripts:


 Very dumb question: if your script execution time is much smaller
than one second, why not simply "while true ; do update ; sleep 1 ; 
done" ?

(Or better, "update ; exec sleep 1" in a runit/s6/... run script.)

 If your script execution time is not negligible compared to one second,
you could replace "update" with "update &".
 If "update"'s execution time can go over one second, then you need to 
make

it reentrant, but it's the same with your SIGHUP and fifo system.

Given the constraints I have (which I left out of the original post) 
it's not a dumb question.


1.  update has to run 60 times a minute.  It's not critical that it run 
every second to the millisecond, but it does have to run 60 times a 
minute.  A solution using "sleep" would not work since it takes a real 
and variable time to run update (between .2 and .5 seconds), and sleep 
is not guaranteed to take exactly 1 second.


2.  update is stateful; it compares the state at its last execution with 
the current state.  For that reason spawning update & will not work 
without a lot of overhead.


2.a) If I was to spawn it, I'd use watch -n 1 update and then I'd be done.

3.  Overhead - I am working with a very limited board with low CPU 
power.  Spawning a process every second adds about 2-3% cpu load.


I went to fairly great lengths to build this script with shell builtins 
rather than spawning processes.  I could (and probably will) rewrite 
this in C, but for now it's become an interesting exercise in shell 
scripting.  And learning something is never dumb.


This does, however, raise the question about watch - does it use sleep 
or does it actually trigger it every second?  Time to look at code.

___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox