長い時間のsetIntervalの件

2018年4月24日 - 未分類

どうも、Raspberry Piだけに該当するようなバグのようです。setIntervalやsetTimeout、node-shceduleで、30分以上の長い時間間隔にすると、指定時間になっても動作しない。30分以下なら、正しく動作する。とんでもないバグです。解決方法は、10分間隔で、ダミーのsetIntervalを入れること。解決策が分かるまで、時間がかかってしまった。

MacOSXでは、1時間以上長いsetIntervalでも動作するので、Raspberry Pi 固有の問題だと言うことになかなか気が付かなかった。

動作する例

setInterval(function(){ console.log((new Date())},10*60*1000);

動作しない例

setInterval(function(){ console.log((new Date())},60*60*1000);

 

こうすれば、1時間以上でも動作する。

setInterval(function(){ console.log((new Date())},10*60*1000);
setInterval(function(){ console.log((new Date())},60*60*1000);

10分間隔の何もしないようなダミーインターバルを入れると上手く動作する。

https://github.com/nodejs/node/issues/4262

これは、nodeのバグかと思いましたが、Raspberry PiのOSが32bit版だということに原因があります。

https://github.com/Samsung/libtuv/blob/master/src/unix/linux-core.c

 

void uv__io_poll(uv_loop_t* loop, int timeout) {
/* A bug in kernels < 2.6.37 makes timeouts larger than ~30 minutes
* effectively infinite on 32 bits architectures. To avoid blocking
* indefinitely, we cap the timeout and poll again if necessary.
*
* Note that "30 minutes" is a simplification because it depends on
* the value of CONFIG_HZ. The magic constant assumes CONFIG_HZ=1200,
* that being the largest value I have seen in the wild (and only once.)
*/
static const int max_safe_timeout = 1789569;


for (;;) {
/* See the comment for max_safe_timeout for an explanation of why
* this is necessary. Executive summary: kernel bug workaround.
*/
if (sizeof(int32_t) == sizeof(long) && timeout >= max_safe_timeout)
timeout = max_safe_timeout;

max_safe_timeout = 1789569;なので、29.8分でタイムアウトします。

Raspbian OSが64bit版になれば、改善されると思われます。

Translate »