{"action":"created","issue":{"url":"https://api.github.com/repos/adhearsion/punchblock/issues/250","labels_url":"https://api.github.com/repos/adhearsion/punchblock/issues/250/labels{/name}","comments_url":"https://api.github.com/repos/adhearsion/punchblock/issues/250/comments","events_url":"https://api.github.com/repos/adhearsion/punchblock/issues/250/events","html_url":"https://github.com/adhearsion/punchblock/pull/250","id":93772111,"number":250,"title":"Fixed a memory leak caused by Punchblock::Translator::Asterisk","user":{"login":"serioja90","id":2454975,"avatar_url":"https://avatars.githubusercontent.com/u/2454975?v=3","gravatar_id":"","url":"https://api.github.com/users/serioja90","html_url":"https://github.com/serioja90","followers_url":"https://api.github.com/users/serioja90/followers","following_url":"https://api.github.com/users/serioja90/following{/other_user}","gists_url":"https://api.github.com/users/serioja90/gists{/gist_id}","starred_url":"https://api.github.com/users/serioja90/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/serioja90/subscriptions","organizations_url":"https://api.github.com/users/serioja90/orgs","repos_url":"https://api.github.com/users/serioja90/repos","events_url":"https://api.github.com/users/serioja90/events{/privacy}","received_events_url":"https://api.github.com/users/serioja90/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":3,"created_at":"2015-07-08T12:05:23Z","updated_at":"2015-07-09T15:44:32Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/adhearsion/punchblock/pulls/250","html_url":"https://github.com/adhearsion/punchblock/pull/250","diff_url":"https://github.com/adhearsion/punchblock/pull/250.diff","patch_url":"https://github.com/adhearsion/punchblock/pull/250.patch"},"body":"There's a memory leak in Punchblock (asterisk platform) caused by `Punchblock::Translator::Asterisk` that detains references to `Punchblock::Translator::Asterisk::Component::Asterisk::AMIAction` objects even after the call is ended.\r\n\r\nPer each call a new `Punchblock::Translator::Asterisk::Component::Asterisk::AMIAction` is created here:\r\n\r\nhttps://github.com/adhearsion/punchblock/blob/develop/lib/punchblock/translator/asterisk.rb#L143\r\n\r\nand then registered into `Punchblock::Translator::Asterisk` as a component object. The problem is that those `Punchblock::Translator::Asterisk::Component::Asterisk::AMIAction` objects are never garbage collected, because the reference to them is never removed.\r\n\r\nThe solution is to deregister the component when the complete event is received.\r\n\r\nThe memory leak could be seen by counting the number of `Punchblock::Translator::Asterisk::Component::Asterisk::AMIAction` in `ObjectSpace`:\r\n\r\n```ruby\r\nObjectSpace.each_object(Punchblock::Translator::Asterisk::Component::Asterisk::AMIAction).count\r\n```\r\n\r\nThe number of those objects grows continuously."},"comment":{"url":"https://api.github.com/repos/adhearsion/punchblock/issues/comments/120042109","html_url":"https://github.com/adhearsion/punchblock/pull/250#issuecomment-120042109","issue_url":"https://api.github.com/repos/adhearsion/punchblock/issues/250","id":120042109,"user":{"login":"serioja90","id":2454975,"avatar_url":"https://avatars.githubusercontent.com/u/2454975?v=3","gravatar_id":"","url":"https://api.github.com/users/serioja90","html_url":"https://github.com/serioja90","followers_url":"https://api.github.com/users/serioja90/followers","following_url":"https://api.github.com/users/serioja90/following{/other_user}","gists_url":"https://api.github.com/users/serioja90/gists{/gist_id}","starred_url":"https://api.github.com/users/serioja90/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/serioja90/subscriptions","organizations_url":"https://api.github.com/users/serioja90/orgs","repos_url":"https://api.github.com/users/serioja90/repos","events_url":"https://api.github.com/users/serioja90/events{/privacy}","received_events_url":"https://api.github.com/users/serioja90/received_events","type":"User","site_admin":false},"created_at":"2015-07-09T15:44:32Z","updated_at":"2015-07-09T15:44:32Z","body":"@benlangfeld do you mean a RSpec test?\r\n\r\nTo test it I've just set up a context in asterisk's dialplan that looks like: \r\n\r\n```\r\n[local-test]\r\nexten => _[0-9]!,1, Answer()\r\nexten => _[0-9]!,n, Wait(2)\r\nexten => _[0-9]!,n, Hangup()\r\n```\r\n\r\nand then perform a bunch of `Originate` actions on the Local channel (ex. `Local/<phone>@local-test/n`).\r\n\r\nA PoC to test it will look like this:\r\n\r\n```ruby\r\n1000.times do\r\n  phone = (rand * 10000).to_i\r\n  to    = \"Local/#{phone}@local-test/n\"\r\n\r\n  options = {\r\n    from: '123',\r\n    timeout: 30,\r\n    controller: MyController,\r\n    controller_metadata: {}\r\n  }\r\n\r\n  Adhearsion::OutboundCall.originate to, options\r\nend\r\n\r\nObjectSpace.each_object(Punchblock::Translator::Asterisk::Component::Asterisk::AMIAction).count\r\n```\r\n\r\nWithout the fix you will get a new `Punchblock::Translator::Asterisk::Component::Asterisk::AMIAction` object even when the call is ended and `GC` passed.\r\n\r\nWith the fix applied the number of those objects will remain equal to the number of `Adhearsion.active_calls.count` and will get back to `0` as soon as there isn't any active call.\r\n\r\nA possible way to check if the fix solves the issue is to check if call related components are removed from `@components` attribute of `Punchblock::Translator::Asterisk` when the call is completed.\r\n\r\nAbout Adhearsion 3: I've never used it, so it'd be harder for me to prepare a pull request with the fix for it. I prefer to focus on the aforementioned test before start studying ahn v3 source code.  "}}