Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

epoll

fivdi11.4kMIT4.0.2

A low-level Node.js binding for the Linux epoll API

epoll, epollpri, poll, pollpri, gpio, interrupt, linux

readme

Build Status npm Version Downloads Per Month

epoll

A low-level Node.js binding for the Linux epoll API for monitoring multiple file descriptors to see if I/O is possible on any of them.

This module was initially written to detect EPOLLPRI events indicating that urgent data is available for reading. EPOLLPRI events are triggered by interrupt generating GPIO pins. The epoll module is used by onoff to detect such interrupts.

epoll supports Node.js versions 10, 12, 14, 16, 18 and 20.

Installation

Note that although it should be possible to install epoll on non-Linux systems the functionality offered by epoll is only available on Linux systems.

npm install epoll

API

  • Epoll(callback) - Constructor. The callback is called when epoll events occur and it gets three arguments (err, fd, events).
  • add(fd, events) - Register file descriptor fd for the event types specified by events.
  • remove(fd) - Deregister file descriptor fd.
  • modify(fd, events) - Change the event types associated with file descriptor fd to those specified by events.
  • close() - Deregisters all file descriptors and free resources.

Event Types

  • Epoll.EPOLLIN
  • Epoll.EPOLLOUT
  • Epoll.EPOLLRDHUP
  • Epoll.EPOLLPRI
  • Epoll.EPOLLERR
  • Epoll.EPOLLHUP
  • Epoll.EPOLLET
  • Epoll.EPOLLONESHOT

Event types can be combined with | when calling add or modify. For example, Epoll.EPOLLPRI | Epoll.EPOLLONESHOT could be passed to add to detect a single GPIO interrupt.

Example - Watching Buttons

The following example shows how epoll can be used to detect interrupts from a momentary push-button connected to GPIO4 (pin P1-7) on the Raspberry Pi. The source code is available in the example directory and can easily be modified for using a different GPIO on the Pi or a different platform such as the BeagleBone.

The first step is to export GPIO4 as an interrupt generating input using the export bash script from the examples directory.

./export

export:

#!/bin/sh
echo 4 > /sys/class/gpio/export
sleep 1
echo in > /sys/class/gpio/gpio4/direction
echo both > /sys/class/gpio/gpio4/edge

Then run watch-button to be notified every time the button is pressed and released. If there is no hardware debounce circuit for the push-button, contact bounce issues are very likely to be visible on the console output. watch-button terminates automatically after 30 seconds.

node watch-button

watch-button:

const Epoll = require('epoll').Epoll;
const fs = require('fs');

const valuefd = fs.openSync('/sys/class/gpio/gpio4/value', 'r');
const buffer = Buffer.alloc(1);

// Create a new Epoll. The callback is the interrupt handler.
const poller = new Epoll((err, fd, events) => {
  // Read GPIO value file. Reading also clears the interrupt.
  fs.readSync(fd, buffer, 0, 1, 0);
  console.log(buffer.toString() === '1' ? 'pressed' : 'released');
});

// Read the GPIO value file before watching to
// prevent an initial unauthentic interrupt.
fs.readSync(valuefd, buffer, 0, 1, 0);

// Start watching for interrupts.
poller.add(valuefd, Epoll.EPOLLPRI);

// Stop watching after 30 seconds.
setTimeout(_ => {
  poller.remove(valuefd).close();
}, 30000);

When watch-button has terminated, GPIO4 can be unexported using the unexport bash script.

./unexport

unexport:

#!/bin/sh
echo 4 > /sys/class/gpio/unexport

Example - Interrupts Per Second

The following example shows how epoll can be used to determine the number of hardware interrupts that can be handled per second on the Raspberry Pi. The source code is available in the example directory and can easily be modified to use different GPIOs on the Raspberry Pi or a different platform such as the BeagleBone.

In this example, GPIO7 is wired to one end of a 1kΩ current limiting resistor and GPIO8 is wired to the other end of the resistor. GPIO7 is an input and GPIO8 is an output.

The first step is to export GPIOs #7 and #8 using the export bash script from the examples directory.

./export

export:

#!/bin/sh
echo 7 > /sys/class/gpio/export
echo 8 > /sys/class/gpio/export
sleep 1
echo in > /sys/class/gpio/gpio7/direction
echo both > /sys/class/gpio/gpio7/edge
echo out > /sys/class/gpio/gpio8/direction

Then run interrupts-per-second. interrupts-per-second toggles the state of the output every time it detects an interrupt on the input. Each toggle will trigger the next interrupt. After five seconds, interrupts-per-second prints the number of interrupts it detected per second.

node interrupts-per-second

interrupts-per-second:

const Epoll = require('../../').Epoll;
const fs = require('fs');

const value = Buffer.alloc(1); // The three Buffers here are global
const zero = Buffer.from('0'); // to improve performance.
const one = Buffer.from('1');

const inputfd = fs.openSync('/sys/class/gpio/gpio7/value', 'r+');
const outputfd = fs.openSync('/sys/class/gpio/gpio8/value', 'r+');

let count = 0;

// Create a new Epoll. The callback is the interrupt handler.
const poller = new Epoll((err, fd, events) => {
  count += 1;

  // Read GPIO value file. Reading also clears the interrupt.
  fs.readSync(inputfd, value, 0, 1, 0);

  // Toggle GPIO value. This will eventually result
  // in the next interrupt being triggered.
  const nextValue = value[0] === zero[0] ? one : zero;
  fs.writeSync(outputfd, nextValue, 0, nextValue.length, 0);
});

let time = process.hrtime(); // Get start time.

// Start watching for interrupts. This will trigger the first interrupt
// as the value file already has data waiting for a read.
poller.add(inputfd, Epoll.EPOLLPRI);

// Print interrupt rate to console after 5 seconds.
setTimeout(_ => {
  time = process.hrtime(time); // Get run time.
  const rate = Math.floor(count / (time[0] + time[1] / 1E9));
  console.log(rate + ' interrupts per second');

  // Stop watching.
  poller.remove(inputfd).close();
}, 5000);

When interrupts-per-second has terminated, GPIOs #7 and #8 can be unexported using the unexport bash script.

./unexport

unexport:

#!/bin/sh
echo 7 > /sys/class/gpio/unexport
echo 8 > /sys/class/gpio/unexport

Here are some results from the "Interrupts Per Second" example.

Raspberry Pi 4 Model B, Raspberry Pi OS (March 4th 2021, Debian 10.8):

node epoll kernel interrupts / sec
v16.0.0 v4.0.1 5.10.17-v7l+ 20112

changelog

4.0.2 - Aug 06 2023

  • update dependencies
  • update information related to supported versions

4.0.1 - Apr 26 2020

  • update performance numbers
  • drop support for node.js 8 and 13, add support for node.js 15 & 16

4.0.0 - Apr 23 2020

  • drop support for node.js 6, add support for node.js 14
  • update dependencies (nan v2.14.1, jshint v2.11.0)
  • use g++-6 on travis

3.0.0 - Sep 21 2019

  • drop support for node.js 4

2.0.10 - Sep 07 2019

  • more linting
  • update dependencies (nan v2.14.0)

2.0.9 - Mar 14 2019

  • update dependencies (nan v2.13.0, jshint v2.10.2)

2.0.8 - Mar 02 2019

  • add simple stub for non-linux installs
  • don't compile epoll.cc on non-linux systems
  • lint with jshint
  • add travis build

2.0.7 - Dec 19 2018

  • fix deprecation warnings on node.js v12 nightly
  • update dependencies (nan v2.12.1, bindings v1.3.1)

2.0.6 - Oct 14 2018

2.0.5 - Oct 13 2018

2.0.4 - Sep 29 2018

  • update dependencies (nan v2.11.1)
  • adapt to V8 7.0: replace v8Value->Int32Value() with Nan::To<int32_t>(v8Value).FromJust()

2.0.3 - Jul 28 2018

  • code style

2.0.2 - Jul 22 2018

  • add coin acceptor stress test
  • replace new Buffer with Buffer.from or Buffer.alloc
  • sleep for one second after exporting gpios to avoid permission issues
  • construct AsyncResource for callback when callback is stored

2.0.1 - Apr 02 2018

  • update dependencies (nan v2.10.0)

2.0.0 - Feb 25 2018

  • update dependencies (nan v2.9.2)
  • fix deprecations
  • drop support for node.js v0.10, v0.12, v5 and v7

1.0.2 - Dec 24 2017

  • don't suppress deprecated-declaration warnings
  • nan 2.8.0

1.0.1 - Nov 04 2017

  • suppress deprecated-declaration warnings
  • document node 9 support

1.0.0 - Oct 15 2017

  • update dependencies (bindings v1.3.0, nan v2.7.0)
  • document supported node versions

0.1.22 - Jun 18 2017

  • nan 2.6.2

0.1.21 - Feb 12 2017

  • require node v0.10 or higher
  • nan 2.5.1

0.1.20 - Jul 22 2016

  • document dependency on Linux
  • nan 2.4.0

0.1.19 - May 03 2016

  • add accessor for closed property to instance template

0.1.18 - Apr 27 2016

  • upgrade to NAN v2.3.2 for Node.js v6.0.0 compatability

0.1.17 - Jan 29 2016

  • nan 2.2.0
  • documentation

0.1.16 - Oct 10 2015

  • documentation
  • nan 2.1.0

0.1.15 - Aug 24 2015

  • fix null passed to callback

0.1.14 - Aug 24 2015

  • nan2 migration

0.1.13 - May 07 2015

  • io.js v2.0.0+ compatibility #13

0.1.12 - Feb 10 2015

  • nan 1.6.2
  • refactored interrupts-per-second example #11

0.1.11 - Jan 17 2015

  • support io.js #10

0.1.10 - Nov 02 2014

  • nan 1.4.0

0.1.9 - Aug 09 2014

  • nan 1.3.0

0.1.8 - Jul 12 2014

  • nan 1.2.0
  • bindings 1.2.1

0.1.7 - May 29 2014

  • Fixed date in History.md

0.1.6 - May 29 2014

0.1.5 - May 04 2014

  • nan 1.0.0 alignment #8

0.1.4 - Apr 18 2014

  • Documented BeagleBone Ångström prerequisites
  • Use bindings for laoding

0.1.3 - Mar 23 2014

  • 0.11.5+ compatibility #7
  • Updated dependencies: nan 0.6.2 -> 0.8.0

0.1.2 - Nov 21 2013

  • 0.11.9+ compatibility #6
  • Updated dependencies: nan 0.5.2 -> 0.6.0

0.1.1 - Nov 19 2013

  • A hopefully successfull attempt to fix an npm install issue

0.1.0 - Nov 18 2013

  • Updated dependencies: nan 0.4.1 -> 0.5.2
  • removed using namespace v8 (bad practice)

0.0.8 - Oct 14 2013

  • Epoll thread code improved (#4)
  • EINTR handling (#3)

0.0.7 - Oct 05 2013

  • closed property added (#1)
  • Segfault issue fixed (#5)
  • add and modify now accept Epoll.EPOLLET as an event (#2)

0.0.6 - Oct 01 2013

  • Example for watching outputs added
  • Tests improved

0.0.5 - Sep 25 2013

  • Link removed from readme

0.0.4 - Sep 25 2013

  • Url in readme fixed so that it displays correctly at npmjs.org, hopefully

0.0.3 - Sep 25 2013

  • Content added to readme
  • Examples for the BeagleBone and RaspberryPi
  • Minor bug fixes
  • Tests improved

0.0.2 - Sep 22 2013

  • Tests extended and improved
  • Allow installation on non-Linux systems but provide no functionality (needed for firmata-pi tests)

0.0.1 - Sep 22 2013

  • Initial release