We recently tried to implement settable date and time on a SOM/9651 using the system config VI - set time.vi, during main application execution. When we did this all loops stopped for up to 45 sec. supposedly while the OS adjusted the time? I dunno.
Working with NI support there is a CAR for set time where using this VI "affects determinism" ...understatement if I've ever heard one This affects 2013 and 2014 as far as I could gather. I was not given the CAR number but apparently it's been fixed in LabVIEW 2015 (specifically sys config 15). Unfortunately, we are standardized on 2014 for now, so upgrading is not an option.
So, I'm simply (or not simply...) looking for a way to update the date/time during regular execution.
I thought to try two options:
-System exec VI calling the OS command to change date
-Script (same command and also called from system exec VI)
Command: date --set="YYYY-MM-DD HH:MM"
I have verified the command and syntax I'm using through the bash shell/ssh and the command works as expected.
When I use system exec vi in LabVIEW to call the date command, the standard error output says "Operation not permitted"
A little research and I've found when I use ssh, I login with admin, which is equivalent to root, I believe. The LabVIEW app runs as a user with less permissions.
I tried calling system exec with "su" before the date command. Standard error was "must be run from terminal". Next was "sudo", and the error was "/bin/sh/: sudo: command not found" I assume sudo isn't installed for security reasons, which makes sense.
I next tried to put my command into a script. Same command into a text file with a *.sh extension. Called from system exec vi. Still get "Operation not permitted" I can tell this would work with the right permissions because the standard output reflects the command and shows the date I requested. I didn't really think this would help, but I wanted to try the "chmod" command on the script file. Again "Operation not permitted"
So, how can I set the date during execution, without using system config VIs?
Also, I wasn't able to find much at ni.com regarding permissions and/or how-to. What can we do and what can't we do within certain permissions? And how can we change permissions? (I would like to avoid having to install the external sudo package both for security reasons and field upgrade simplicity.)
Thanks for any/all ideas and help, in advance. I'm not that Linux savy, so be gentle. Thanks.
Solved! Go to Solution.
The reason you can't call the date command through System Exec is because the capabilities given to LabVIEW are not inheritable by a command called through the shell.
The LabVIEW process does have permission to change the date. You can see this here:
# getcap /usr/local/natinst/labview/lvrt
/usr/local/natinst/labview/lvrt = cap_net_bind_service,cap_ipc_lock,cap_sys_rawio,cap_sys_boot,cap_sys_nice,cap_sys_time+ep
cap_sys_time is the required capability and it is set.
You need to call the function settimeofday() directly with a Call Library Function Node.
Unfortunately the LabVIEW type for timestamp is not compatible with Linux. However, it can be converted fairly easily. I've attached a simple VI to convert the format and call the system library to set the time. Since the LabVIEW process has access to call that API, you should not see the -EPERM error you would see from an executable without that capability.
Thank you so much! I can confirm that VI works exactly as expected (sets date and time) and does not interfere with loop operation nearly as much as the system config set time. While our loops all jumped into the seconds range, it was only for a 1 (maybe 2) loop iterations. Completely managable and understandable. This is what I'd expect (just not 45 sec. like the sys config set time). I'd say this is solved!
Also...wow! Great help! Very quick reply with fully functioning VI. I'm impressed. I wish all my issues turned out like this...
Another option to consider is that NI supports a few different options for standard time sync protocols. Depending on why you need to set the clock, it could be that using a standard protocol like IEEE-1588 (PTP) or (S)NTP for setting the time will give you better behavior than setting it "manually" from LabVIEW or SysConfig. In particular, if you find yourself needing to periodically re-adjust the time as your target's clock drifts from your global reference, you'll affect your loops each time you have to do that. With a full time sync protocol, after initially setting the time, it will gradually adjust the observed clock frequency so that there are no further discontinuities in the clock.
Thanks for replying as well! Those are certianly valid options for people to consider. Unfortunately, we really don't need the sync capabilities of 1588. Only one RIO is the system has time that matters. Also, the system is on it's own private network and there isn't an sntp server. So neither of those are options.
Really, we just wanted a way for an end user to update the clock, if needed. The end user won't have MAX. So, basic time setting is all we needed. We just got stuck with the sys config bug, but we're back on track now.
So, a quick followup for anyone else that find this. While the solution provided here does change the time, and there is some helpful info about permissions and scripts, this approach doesn't quite solve the original problem.
The original problem is when the system time is changed in Linux RT by the system config VIs (and this script apparently) any timed loops will be interupted/paused. I've now see anywhere from 45 sec. to 5 min. before they are responsive again. The CAR is 415146, and it's fixed in 14.1.
I think I missed seeing the bug when I tested the script because setting the time forward doesn't cause the problem, but setting it backwards does. Interesting.
Anyway, I've spent way too long on this already, I guess we're restricted to restarting the system whenever we want to change the time. Joe/Scot thanks again for helping/replying here!
time handling usually is a can of worms - beginning with the question what kind of kind of time you're actually caring about - the wallclock (call me at 1500 CET) is *very* different from time spans (valve must for 100ms). Keep them *strictly* separate, especially if any kind of time synchronization is involved - otherwise *bad* things can happen, when you least expect this. (some friends of mine are field technicians and regularily have big trouble because developers never cared about that).
Fortunately, Unix (therefore Linux) has mechanisms to cope w/ that, via different clocks.
(see clock_gettime() manpage for details), mainly:
--> the (local) wall clock. appointments in your calendar are measured by this one.
--> will be directly changed by 'date -s ...' / clock_settime(), so can jump arbitrarily (!)
--> smoothly adjusted by ntpd (by adusting frequency - so takes some time to tune in)
--> just counting the ticks since bootup, not affected by clock_settime(), but fine frequency adjustments from NTP (drift adjustment)
--> might be paused by suspend
--> like CLOCK_MONOTONIC, but not affected by NTPs drift adjustments
--> usually derived from CPU clock(s), so there might be (small) hw-dependent jitter and drift
--> like CLOCK_MONOTONIC, but w/o suspend pauses
--> so, if you're controlling proceses in combination w/ suspend (eg. for powersave), this is your clock
Note that these are clocks are *different* from usual hw-RTCs (as eg. found on PCs) - the kernel just initializes CLOCK_REALTIME from the primary RTC (if present and valid) on bootup.
Be careful w/ clock_settime (or date command): this *directly* changes CLOCK_REALTIME arbitrarily - it'll make huge jumps into future or past. Applications depending on that clock might not be aware of that.
To solve that problem, NTPd (unless you force it to) doesn't set the reference time directly, but smoothly adjusts the system clock frequency, so it tunes in w/ the reference clock (note: you can also use it to sync against locally attached reference clocks, eg. gps receiver, atomic clocks, etc). Basicly two things happen in parallel:
a) adjust the base clock frequency to the reference frequency (adjtimex+co)
b) correct the offset of CLOCK_REALTIME in small steps (usually w/o counting backwards) until it fits the reference (takes some time)
c) write CLOCK_REALTIME to the (usually less precise) RTC (if present)
If the wallclock differs too much from the reference, it gives up - unless you force it to be brute an just set the clock directly (dont do it while applications running).
Long story short: 60 secs after 23:59 doesn't necessary mean 00:00 (yeah, leap seconds may appear).
Actually, I have no idea whether LV cares about the different clocks, but it *really* should - and so should you.
Thank you for the thoughtful writeup on the various different notions of time in Linux (and hinting at some of the pitfalls with incorrect selection).
If you're interested, LVRT's nominal use of time is based on CLOCK_MONOTONIC to get as close to an expected, externally-accurate period for timing. LVRT provides access to CLOCK_REALTIME, mostly for timestamping or informational purposes, but it can be used to drive the execution of code, but you have to do a little extra work and design with a different set of interfaces.
If you're interested, LVRT's nominal use of time is based on CLOCK_MONOTONIC to get as close to an expected, externally-accurate period for timing.
Note: if you need more than 32 timers per process, you should go for timerfd.
Anyways,especially for RT, you should have an own thread (w/ proper sched settings) per timer that just sleeps in read() until it fires - that should give you best accuracy and simple sw architecture at the same time. Threads are pretty cheap on Linux, and via timerfd you can easily control which one shall receive the event.
LVRT provides access to CLOCK_REALTIME, mostly for timestamping or informational purposes, but it can be used to drive the execution of code, but you have to do a little extra work and design with a different set of interfaces.
I'd advice all time related functions to accept a clock ID. Relative timers would default to CLOCK_MONOTONIC, low precision timers (eg. timeouts that dont need high precision and are unlikely to fire) could use CLOCK_MONOTONIC_COARSE which is a bit cheaper and allows the kernel to always put (and leave) it in the biggest wheel (more efficent, less accurate).