{"action":"created","issue":{"url":"https://api.github.com/repos/iojs/io.js/issues/1264","labels_url":"https://api.github.com/repos/iojs/io.js/issues/1264/labels{/name}","comments_url":"https://api.github.com/repos/iojs/io.js/issues/1264/comments","events_url":"https://api.github.com/repos/iojs/io.js/issues/1264/events","html_url":"https://github.com/iojs/io.js/issues/1264","id":64403468,"number":1264,"title":"unref'd timers running in beforeExit time","user":{"login":"brycebaril","id":126482,"avatar_url":"https://avatars.githubusercontent.com/u/126482?v=3","gravatar_id":"","url":"https://api.github.com/users/brycebaril","html_url":"https://github.com/brycebaril","followers_url":"https://api.github.com/users/brycebaril/followers","following_url":"https://api.github.com/users/brycebaril/following{/other_user}","gists_url":"https://api.github.com/users/brycebaril/gists{/gist_id}","starred_url":"https://api.github.com/users/brycebaril/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/brycebaril/subscriptions","organizations_url":"https://api.github.com/users/brycebaril/orgs","repos_url":"https://api.github.com/users/brycebaril/repos","events_url":"https://api.github.com/users/brycebaril/events{/privacy}","received_events_url":"https://api.github.com/users/brycebaril/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/iojs/io.js/labels/timers","name":"timers","color":"f7c6c7"}],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":7,"created_at":"2015-03-26T00:29:14Z","updated_at":"2015-03-26T17:18:48Z","closed_at":null,"body":"When working out this test case for #1152 I came up with this:\r\n\r\n```js\r\nvar assert = require(\"assert\")\r\nvar intervals = 0\r\nvar i = setInterval(function () {\r\n  intervals++\r\n  i.unref()\r\n  eatTime()\r\n}, 10)\r\n\r\nfunction eatTime() {\r\n  // the goal of this function is to take longer than 10ms, i.e. longer than the interval\r\n  var count = 0\r\n  while (count++ < 1e7) {\r\n    Math.random()\r\n  }\r\n}\r\n\r\nprocess.on(\"exit\", function () {\r\n  assert.equal(intervals, 1)\r\n})\r\n```\r\n\r\nNote -- this requires the patch in #1152 to even terminate, or running Node.js 0.12+ which already has that fix.\r\n\r\nI think what happens here is the blocking time causes the repeat time to trigger and the unreferenced timer gets executed in the `beforeExit` timeframe (https://github.com/joyent/node/commit/a2eeb43) when it shouldn't be. This can result in your application not terminating when it should, and functions that should not be executed being run.\r\n\r\nThis is a separate bug than #1151 (with fix #1152) and is not fixed by #1231"},"comment":{"url":"https://api.github.com/repos/iojs/io.js/issues/comments/86630388","html_url":"https://github.com/iojs/io.js/issues/1264#issuecomment-86630388","issue_url":"https://api.github.com/repos/iojs/io.js/issues/1264","id":86630388,"user":{"login":"brycebaril","id":126482,"avatar_url":"https://avatars.githubusercontent.com/u/126482?v=3","gravatar_id":"","url":"https://api.github.com/users/brycebaril","html_url":"https://github.com/brycebaril","followers_url":"https://api.github.com/users/brycebaril/followers","following_url":"https://api.github.com/users/brycebaril/following{/other_user}","gists_url":"https://api.github.com/users/brycebaril/gists{/gist_id}","starred_url":"https://api.github.com/users/brycebaril/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/brycebaril/subscriptions","organizations_url":"https://api.github.com/users/brycebaril/orgs","repos_url":"https://api.github.com/users/brycebaril/repos","events_url":"https://api.github.com/users/brycebaril/events{/privacy}","received_events_url":"https://api.github.com/users/brycebaril/received_events","type":"User","site_admin":false},"created_at":"2015-03-26T17:18:48Z","updated_at":"2015-03-26T17:18:48Z","body":"@Fishrock123 The wait is required because the interval has to be run to leak the handle. It turns out it doesn't even need to be blocking time, E.g.\r\n\r\n```\r\nsetTimeout(function () { /* never run */ }, 10000)\r\nsetInterval(setImmediate, 100, process.exit).unref()\r\nprocess.on('exit', function () { console.log(process._getActiveHandles()) })\r\n```\r\n\r\nWill also leak the setImmediate handle.\r\n\r\nLikewise for this one the cpu-burn-loop is required to make it something that *would* have been run during `beforeExit` if it wasn't already unreferenced. Then by making each run take long enough it would run again, we can make it get run again.\r\n\r\nThis is also why these two issues are so intertwined -- triggering this issue without the #1152 fix will leak the handles indefinitely. Leaking the handles will increase the chance of this issue.\r\n\r\n@bnoordhuis Any guess on a timeframe for the rewrite? We're running into timer issues with io.js in real applications now, holding us back."}}