{"action":"created","issue":{"url":"https://api.github.com/repos/SFML/SFML/issues/1154","repository_url":"https://api.github.com/repos/SFML/SFML","labels_url":"https://api.github.com/repos/SFML/SFML/issues/1154/labels{/name}","comments_url":"https://api.github.com/repos/SFML/SFML/issues/1154/comments","events_url":"https://api.github.com/repos/SFML/SFML/issues/1154/events","html_url":"https://github.com/SFML/SFML/pull/1154","id":179053618,"number":1154,"title":"Fixed stack overflow in SoundStream::fillAndPushBuffer() when the underlying stream fails.","user":{"login":"Cobaltergeist","id":2526440,"avatar_url":"https://avatars.githubusercontent.com/u/2526440?v=3","gravatar_id":"","url":"https://api.github.com/users/Cobaltergeist","html_url":"https://github.com/Cobaltergeist","followers_url":"https://api.github.com/users/Cobaltergeist/followers","following_url":"https://api.github.com/users/Cobaltergeist/following{/other_user}","gists_url":"https://api.github.com/users/Cobaltergeist/gists{/gist_id}","starred_url":"https://api.github.com/users/Cobaltergeist/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Cobaltergeist/subscriptions","organizations_url":"https://api.github.com/users/Cobaltergeist/orgs","repos_url":"https://api.github.com/users/Cobaltergeist/repos","events_url":"https://api.github.com/users/Cobaltergeist/events{/privacy}","received_events_url":"https://api.github.com/users/Cobaltergeist/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/SFML/SFML/labels/bug","name":"bug","color":"ff4242"},{"url":"https://api.github.com/repos/SFML/SFML/labels/m:sfml-audio","name":"m:sfml-audio","color":"cccccc"},{"url":"https://api.github.com/repos/SFML/SFML/labels/s:undecided","name":"s:undecided","color":"ffe20a"}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":6,"created_at":"2016-09-24T21:41:11Z","updated_at":"2016-10-03T08:35:38Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/SFML/SFML/pulls/1154","html_url":"https://github.com/SFML/SFML/pull/1154","diff_url":"https://github.com/SFML/SFML/pull/1154.diff","patch_url":"https://github.com/SFML/SFML/pull/1154.patch"},"body":"While I was testing #1118, I decided to see what happened when I made the underlying file used by a `SoundStream` unavailable mid-play, (for example, putting the audio file on a flash drive and yanking it while my test program was running). The program promptly segfaulted. My debugger showed that the `SoundStream`'s processor thread had hundreds of frames in `fillAndPushBuffer()`.\r\n\r\nThe underlying issue was with `fillAndPushBuffer`'s retry mechanism. For a looping sound, a read that returns false is assumed to be at the EOF, so the function triggers a seek to the beginning and retries. But when that read contains 0 samples, it tries to reuse that buffer by calling itself recursively.\r\n\r\nThe issue arises when the underlying stream fails. Like any sane implementation that can only return a `UInt64` to `read()` calls, it will start returning 0 to all requests for data once it errors out. `Music::onGetData()` correctly handles the zero-read and returns false, but `SoundStream::fillAndPushBuffer` expects this to mean it can retry, and it chokes. Specifically, it keeps calling itself recursively and burns through its stack, segfaulting the whole program.\r\n\r\nSince I can't change the `onGetData()` and `read()` signatures to propagate the error status in a minor version, the most practical fix is to interpret multiple consecutive zero-reads as an error. I did this by converting the false-read handling code into a retry loop. Currently I have a `BufferRetries` enum constant, set to 2, for 3 tries total. If the third read fails, it leaves the loop and sets `requestStop`, which shuts the thread down as if a non-looping sound had finished playing. My [test program's](http://pastebin.com/W85LkrAX) polling loop sees the `SoundStream` stop, and quits cleanly.\r\n\r\nSince this modifies some of the same code as #1118, I fully expect a merge conflict. I will rebase this PR to account for the `immediateLoop` parameter once the other one is merged."},"comment":{"url":"https://api.github.com/repos/SFML/SFML/issues/comments/251053476","html_url":"https://github.com/SFML/SFML/pull/1154#issuecomment-251053476","issue_url":"https://api.github.com/repos/SFML/SFML/issues/1154","id":251053476,"user":{"login":"nabijaczleweli","id":6709544,"avatar_url":"https://avatars.githubusercontent.com/u/6709544?v=3","gravatar_id":"","url":"https://api.github.com/users/nabijaczleweli","html_url":"https://github.com/nabijaczleweli","followers_url":"https://api.github.com/users/nabijaczleweli/followers","following_url":"https://api.github.com/users/nabijaczleweli/following{/other_user}","gists_url":"https://api.github.com/users/nabijaczleweli/gists{/gist_id}","starred_url":"https://api.github.com/users/nabijaczleweli/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nabijaczleweli/subscriptions","organizations_url":"https://api.github.com/users/nabijaczleweli/orgs","repos_url":"https://api.github.com/users/nabijaczleweli/repos","events_url":"https://api.github.com/users/nabijaczleweli/events{/privacy}","received_events_url":"https://api.github.com/users/nabijaczleweli/received_events","type":"User","site_admin":false},"created_at":"2016-10-03T08:35:38Z","updated_at":"2016-10-03T08:35:38Z","body":"Praise the SFMLBuildMaster"}}
{"actor":{"display_login":"nabijaczleweli"}}