{"action":"created","comment":{"url":"https://api.github.com/repos/ethereum/go-ethereum/pulls/comments/45174259","id":45174259,"diff_hunk":"@@ -426,34 +408,52 @@ func (d *Downloader) syncWithPeer(p *peer, hash common.Hash, td *big.Int) (err e\n \t\t\tglog.V(logger.Debug).Infof(\"Fast syncing until pivot block #%d\", pivot)\n \t\t}\n \t\td.queue.Prepare(origin+1, d.mode, pivot)\n-\n \t\tif d.syncInitHook != nil {\n \t\t\td.syncInitHook(origin, latest)\n \t\t}\n-\t\terrc := make(chan error, 4)\n-\t\tgo func() { errc <- d.fetchHeaders(p, td, origin+1) }() // Headers are always retrieved\n-\t\tgo func() { errc <- d.fetchBodies(origin + 1) }()       // Bodies are retrieved during normal and fast sync\n-\t\tgo func() { errc <- d.fetchReceipts(origin + 1) }()     // Receipts are retrieved during fast sync\n-\t\tgo func() { errc <- d.fetchNodeData() }()               // Node state data is retrieved during fast sync\n-\n-\t\t// If any fetcher fails, cancel the others\n-\t\tvar fail error\n-\t\tfor i := 0; i < cap(errc); i++ {\n-\t\t\tif err := <-errc; err != nil {\n-\t\t\t\tif fail == nil {\n-\t\t\t\t\tfail = err\n-\t\t\t\t\td.cancel()\n-\t\t\t\t}\n-\t\t\t}\n-\t\t}\n-\t\treturn fail\n+\t\treturn d.spawnSync(\n+\t\t\tfunc() error { return d.fetchHeaders(p, td, origin+1) }, // Headers are always retrieved\n+\t\t\tfunc() error { return d.fetchBodies(origin + 1) },       // Bodies are retrieved during normal and fast sync\n+\t\t\tfunc() error { return d.fetchReceipts(origin + 1) },     // Receipts are retrieved during fast sync\n+\t\t\tfunc() error { return d.fetchNodeData() },               // Node state data is retrieved during fast sync\n+\t\t)\n \n \tdefault:\n \t\t// Something very wrong, stop right here\n \t\tglog.V(logger.Error).Infof(\"Unsupported eth protocol: %d\", p.version)\n \t\treturn errBadPeer\n \t}\n-\treturn nil\n+}\n+\n+// spawns all given fetcher functions in separate goroutines,\n+// returning the first error that appears.\n+func (d *Downloader) spawnSync(fetchers ...func() error) error {\n+\t// Run the block processor and all fetchers.\n+\tvar wg sync.WaitGroup\n+\terrc := make(chan error, len(fetchers)+1)\n+\twg.Add(len(fetchers) + 1)\n+\tgo func() { errc <- d.process(); wg.Done() }()\n+\tfor _, fn := range fetchers {\n+\t\tfn := fn\n+\t\tgo func() { errc <- fn(); wg.Done() }()\n+\t}","path":"eth/downloader/downloader.go","position":151,"original_position":151,"commit_id":"8a2a755d286c1b623a7f490ff31de232dff2e2cf","original_commit_id":"8a2a755d286c1b623a7f490ff31de232dff2e2cf","user":{"login":"karalabe","id":129561,"avatar_url":"https://avatars.githubusercontent.com/u/129561?v=3","gravatar_id":"","url":"https://api.github.com/users/karalabe","html_url":"https://github.com/karalabe","followers_url":"https://api.github.com/users/karalabe/followers","following_url":"https://api.github.com/users/karalabe/following{/other_user}","gists_url":"https://api.github.com/users/karalabe/gists{/gist_id}","starred_url":"https://api.github.com/users/karalabe/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/karalabe/subscriptions","organizations_url":"https://api.github.com/users/karalabe/orgs","repos_url":"https://api.github.com/users/karalabe/repos","events_url":"https://api.github.com/users/karalabe/events{/privacy}","received_events_url":"https://api.github.com/users/karalabe/received_events","type":"User","site_admin":false},"body":"AFAIK, it's better practice to use `defer wg.Done()`, which would ensure that it is called even in the case of a panic. I'm aware that in out case we don't capture exceptions, but it might be a nice touch.","created_at":"2015-11-18T09:03:25Z","updated_at":"2015-11-18T09:03:25Z","html_url":"https://github.com/ethereum/go-ethereum/pull/1980#discussion_r45174259","pull_request_url":"https://api.github.com/repos/ethereum/go-ethereum/pulls/1980","_links":{"self":{"href":"https://api.github.com/repos/ethereum/go-ethereum/pulls/comments/45174259"},"html":{"href":"https://github.com/ethereum/go-ethereum/pull/1980#discussion_r45174259"},"pull_request":{"href":"https://api.github.com/repos/ethereum/go-ethereum/pulls/1980"}}},"pull_request":{"url":"https://api.github.com/repos/ethereum/go-ethereum/pulls/1980","id":50710257,"html_url":"https://github.com/ethereum/go-ethereum/pull/1980","diff_url":"https://github.com/ethereum/go-ethereum/pull/1980.diff","patch_url":"https://github.com/ethereum/go-ethereum/pull/1980.patch","issue_url":"https://api.github.com/repos/ethereum/go-ethereum/issues/1980","number":1980,"state":"open","locked":false,"title":"eth/downloader: don't hang for spurious deliveries","user":{"login":"fjl","id":6915,"avatar_url":"https://avatars.githubusercontent.com/u/6915?v=3","gravatar_id":"","url":"https://api.github.com/users/fjl","html_url":"https://github.com/fjl","followers_url":"https://api.github.com/users/fjl/followers","following_url":"https://api.github.com/users/fjl/following{/other_user}","gists_url":"https://api.github.com/users/fjl/gists{/gist_id}","starred_url":"https://api.github.com/users/fjl/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/fjl/subscriptions","organizations_url":"https://api.github.com/users/fjl/orgs","repos_url":"https://api.github.com/users/fjl/repos","events_url":"https://api.github.com/users/fjl/events{/privacy}","received_events_url":"https://api.github.com/users/fjl/received_events","type":"User","site_admin":false},"body":"Unexpected deliveries could block indefinitely if they arrived at the\r\nright time. The quick fix is to ensure that the cancellation channel is\r\nalways closed when the sync ends, unblocking any deliveries. Also remove\r\nthe atomic check for whether a sync is currently running because it\r\ndoesn't help and can be misleading.","created_at":"2015-11-14T00:48:28Z","updated_at":"2015-11-18T09:03:25Z","closed_at":null,"merged_at":null,"merge_commit_sha":"68b8ffb425c3da3928d3ed111a53d3bcbd695dfc","assignee":null,"milestone":{"url":"https://api.github.com/repos/ethereum/go-ethereum/milestones/20","html_url":"https://github.com/ethereum/go-ethereum/milestones/1.4.0","labels_url":"https://api.github.com/repos/ethereum/go-ethereum/milestones/20/labels","id":1299388,"number":20,"title":"1.4.0","description":"","creator":{"login":"obscuren","id":6264126,"avatar_url":"https://avatars.githubusercontent.com/u/6264126?v=3","gravatar_id":"","url":"https://api.github.com/users/obscuren","html_url":"https://github.com/obscuren","followers_url":"https://api.github.com/users/obscuren/followers","following_url":"https://api.github.com/users/obscuren/following{/other_user}","gists_url":"https://api.github.com/users/obscuren/gists{/gist_id}","starred_url":"https://api.github.com/users/obscuren/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/obscuren/subscriptions","organizations_url":"https://api.github.com/users/obscuren/orgs","repos_url":"https://api.github.com/users/obscuren/repos","events_url":"https://api.github.com/users/obscuren/events{/privacy}","received_events_url":"https://api.github.com/users/obscuren/received_events","type":"User","site_admin":false},"open_issues":16,"closed_issues":6,"state":"open","created_at":"2015-09-10T13:53:50Z","updated_at":"2015-11-17T18:39:43Z","due_on":null,"closed_at":null},"commits_url":"https://api.github.com/repos/ethereum/go-ethereum/pulls/1980/commits","review_comments_url":"https://api.github.com/repos/ethereum/go-ethereum/pulls/1980/comments","review_comment_url":"https://api.github.com/repos/ethereum/go-ethereum/pulls/comments{/number}","comments_url":"https://api.github.com/repos/ethereum/go-ethereum/issues/1980/comments","statuses_url":"https://api.github.com/repos/ethereum/go-ethereum/statuses/8a2a755d286c1b623a7f490ff31de232dff2e2cf","head":{"label":"fjl:downloader-deliver-hang","ref":"downloader-deliver-hang","sha":"8a2a755d286c1b623a7f490ff31de232dff2e2cf","user":{"login":"fjl","id":6915,"avatar_url":"https://avatars.githubusercontent.com/u/6915?v=3","gravatar_id":"","url":"https://api.github.com/users/fjl","html_url":"https://github.com/fjl","followers_url":"https://api.github.com/users/fjl/followers","following_url":"https://api.github.com/users/fjl/following{/other_user}","gists_url":"https://api.github.com/users/fjl/gists{/gist_id}","starred_url":"https://api.github.com/users/fjl/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/fjl/subscriptions","organizations_url":"https://api.github.com/users/fjl/orgs","repos_url":"https://api.github.com/users/fjl/repos","events_url":"https://api.github.com/users/fjl/events{/privacy}","received_events_url":"https://api.github.com/users/fjl/received_events","type":"User","site_admin":false},"repo":{"id":24951427,"name":"go-ethereum","full_name":"fjl/go-ethereum","owner":{"login":"fjl","id":6915,"avatar_url":"https://avatars.githubusercontent.com/u/6915?v=3","gravatar_id":"","url":"https://api.github.com/users/fjl","html_url":"https://github.com/fjl","followers_url":"https://api.github.com/users/fjl/followers","following_url":"https://api.github.com/users/fjl/following{/other_user}","gists_url":"https://api.github.com/users/fjl/gists{/gist_id}","starred_url":"https://api.github.com/users/fjl/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/fjl/subscriptions","organizations_url":"https://api.github.com/users/fjl/orgs","repos_url":"https://api.github.com/users/fjl/repos","events_url":"https://api.github.com/users/fjl/events{/privacy}","received_events_url":"https://api.github.com/users/fjl/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/fjl/go-ethereum","description":"Work fork of go-ethereum.","fork":true,"url":"https://api.github.com/repos/fjl/go-ethereum","forks_url":"https://api.github.com/repos/fjl/go-ethereum/forks","keys_url":"https://api.github.com/repos/fjl/go-ethereum/keys{/key_id}","collaborators_url":"https://api.github.com/repos/fjl/go-ethereum/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/fjl/go-ethereum/teams","hooks_url":"https://api.github.com/repos/fjl/go-ethereum/hooks","issue_events_url":"https://api.github.com/repos/fjl/go-ethereum/issues/events{/number}","events_url":"https://api.github.com/repos/fjl/go-ethereum/events","assignees_url":"https://api.github.com/repos/fjl/go-ethereum/assignees{/user}","branches_url":"https://api.github.com/repos/fjl/go-ethereum/branches{/branch}","tags_url":"https://api.github.com/repos/fjl/go-ethereum/tags","blobs_url":"https://api.github.com/repos/fjl/go-ethereum/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/fjl/go-ethereum/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/fjl/go-ethereum/git/refs{/sha}","trees_url":"https://api.github.com/repos/fjl/go-ethereum/git/trees{/sha}","statuses_url":"https://api.github.com/repos/fjl/go-ethereum/statuses/{sha}","languages_url":"https://api.github.com/repos/fjl/go-ethereum/languages","stargazers_url":"https://api.github.com/repos/fjl/go-ethereum/stargazers","contributors_url":"https://api.github.com/repos/fjl/go-ethereum/contributors","subscribers_url":"https://api.github.com/repos/fjl/go-ethereum/subscribers","subscription_url":"https://api.github.com/repos/fjl/go-ethereum/subscription","commits_url":"https://api.github.com/repos/fjl/go-ethereum/commits{/sha}","git_commits_url":"https://api.github.com/repos/fjl/go-ethereum/git/commits{/sha}","comments_url":"https://api.github.com/repos/fjl/go-ethereum/comments{/number}","issue_comment_url":"https://api.github.com/repos/fjl/go-ethereum/issues/comments{/number}","contents_url":"https://api.github.com/repos/fjl/go-ethereum/contents/{+path}","compare_url":"https://api.github.com/repos/fjl/go-ethereum/compare/{base}...{head}","merges_url":"https://api.github.com/repos/fjl/go-ethereum/merges","archive_url":"https://api.github.com/repos/fjl/go-ethereum/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/fjl/go-ethereum/downloads","issues_url":"https://api.github.com/repos/fjl/go-ethereum/issues{/number}","pulls_url":"https://api.github.com/repos/fjl/go-ethereum/pulls{/number}","milestones_url":"https://api.github.com/repos/fjl/go-ethereum/milestones{/number}","notifications_url":"https://api.github.com/repos/fjl/go-ethereum/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/fjl/go-ethereum/labels{/name}","releases_url":"https://api.github.com/repos/fjl/go-ethereum/releases{/id}","created_at":"2014-10-08T17:12:04Z","updated_at":"2015-05-29T23:48:03Z","pushed_at":"2015-11-17T22:11:14Z","git_url":"git://github.com/fjl/go-ethereum.git","ssh_url":"git@github.com:fjl/go-ethereum.git","clone_url":"https://github.com/fjl/go-ethereum.git","svn_url":"https://github.com/fjl/go-ethereum","homepage":"","size":49168,"stargazers_count":0,"watchers_count":0,"language":"Go","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"ethereum:develop","ref":"develop","sha":"10475f444c9ef0f5f800ccdb03d2ba34b5bf4026","user":{"login":"ethereum","id":6250754,"avatar_url":"https://avatars.githubusercontent.com/u/6250754?v=3","gravatar_id":"","url":"https://api.github.com/users/ethereum","html_url":"https://github.com/ethereum","followers_url":"https://api.github.com/users/ethereum/followers","following_url":"https://api.github.com/users/ethereum/following{/other_user}","gists_url":"https://api.github.com/users/ethereum/gists{/gist_id}","starred_url":"https://api.github.com/users/ethereum/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ethereum/subscriptions","organizations_url":"https://api.github.com/users/ethereum/orgs","repos_url":"https://api.github.com/users/ethereum/repos","events_url":"https://api.github.com/users/ethereum/events{/privacy}","received_events_url":"https://api.github.com/users/ethereum/received_events","type":"Organization","site_admin":false},"repo":{"id":15452919,"name":"go-ethereum","full_name":"ethereum/go-ethereum","owner":{"login":"ethereum","id":6250754,"avatar_url":"https://avatars.githubusercontent.com/u/6250754?v=3","gravatar_id":"","url":"https://api.github.com/users/ethereum","html_url":"https://github.com/ethereum","followers_url":"https://api.github.com/users/ethereum/followers","following_url":"https://api.github.com/users/ethereum/following{/other_user}","gists_url":"https://api.github.com/users/ethereum/gists{/gist_id}","starred_url":"https://api.github.com/users/ethereum/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ethereum/subscriptions","organizations_url":"https://api.github.com/users/ethereum/orgs","repos_url":"https://api.github.com/users/ethereum/repos","events_url":"https://api.github.com/users/ethereum/events{/privacy}","received_events_url":"https://api.github.com/users/ethereum/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/ethereum/go-ethereum","description":"Official golang implementation of the Ethereum protocol","fork":false,"url":"https://api.github.com/repos/ethereum/go-ethereum","forks_url":"https://api.github.com/repos/ethereum/go-ethereum/forks","keys_url":"https://api.github.com/repos/ethereum/go-ethereum/keys{/key_id}","collaborators_url":"https://api.github.com/repos/ethereum/go-ethereum/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/ethereum/go-ethereum/teams","hooks_url":"https://api.github.com/repos/ethereum/go-ethereum/hooks","issue_events_url":"https://api.github.com/repos/ethereum/go-ethereum/issues/events{/number}","events_url":"https://api.github.com/repos/ethereum/go-ethereum/events","assignees_url":"https://api.github.com/repos/ethereum/go-ethereum/assignees{/user}","branches_url":"https://api.github.com/repos/ethereum/go-ethereum/branches{/branch}","tags_url":"https://api.github.com/repos/ethereum/go-ethereum/tags","blobs_url":"https://api.github.com/repos/ethereum/go-ethereum/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/ethereum/go-ethereum/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/ethereum/go-ethereum/git/refs{/sha}","trees_url":"https://api.github.com/repos/ethereum/go-ethereum/git/trees{/sha}","statuses_url":"https://api.github.com/repos/ethereum/go-ethereum/statuses/{sha}","languages_url":"https://api.github.com/repos/ethereum/go-ethereum/languages","stargazers_url":"https://api.github.com/repos/ethereum/go-ethereum/stargazers","contributors_url":"https://api.github.com/repos/ethereum/go-ethereum/contributors","subscribers_url":"https://api.github.com/repos/ethereum/go-ethereum/subscribers","subscription_url":"https://api.github.com/repos/ethereum/go-ethereum/subscription","commits_url":"https://api.github.com/repos/ethereum/go-ethereum/commits{/sha}","git_commits_url":"https://api.github.com/repos/ethereum/go-ethereum/git/commits{/sha}","comments_url":"https://api.github.com/repos/ethereum/go-ethereum/comments{/number}","issue_comment_url":"https://api.github.com/repos/ethereum/go-ethereum/issues/comments{/number}","contents_url":"https://api.github.com/repos/ethereum/go-ethereum/contents/{+path}","compare_url":"https://api.github.com/repos/ethereum/go-ethereum/compare/{base}...{head}","merges_url":"https://api.github.com/repos/ethereum/go-ethereum/merges","archive_url":"https://api.github.com/repos/ethereum/go-ethereum/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/ethereum/go-ethereum/downloads","issues_url":"https://api.github.com/repos/ethereum/go-ethereum/issues{/number}","pulls_url":"https://api.github.com/repos/ethereum/go-ethereum/pulls{/number}","milestones_url":"https://api.github.com/repos/ethereum/go-ethereum/milestones{/number}","notifications_url":"https://api.github.com/repos/ethereum/go-ethereum/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/ethereum/go-ethereum/labels{/name}","releases_url":"https://api.github.com/repos/ethereum/go-ethereum/releases{/id}","created_at":"2013-12-26T13:05:46Z","updated_at":"2015-11-17T15:15:45Z","pushed_at":"2015-11-18T00:23:50Z","git_url":"git://github.com/ethereum/go-ethereum.git","ssh_url":"git@github.com:ethereum/go-ethereum.git","clone_url":"https://github.com/ethereum/go-ethereum.git","svn_url":"https://github.com/ethereum/go-ethereum","homepage":"http://ethereum.github.io/go-ethereum/","size":63979,"stargazers_count":729,"watchers_count":729,"language":"Go","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":247,"mirror_url":null,"open_issues_count":133,"forks":247,"open_issues":133,"watchers":729,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/ethereum/go-ethereum/pulls/1980"},"html":{"href":"https://github.com/ethereum/go-ethereum/pull/1980"},"issue":{"href":"https://api.github.com/repos/ethereum/go-ethereum/issues/1980"},"comments":{"href":"https://api.github.com/repos/ethereum/go-ethereum/issues/1980/comments"},"review_comments":{"href":"https://api.github.com/repos/ethereum/go-ethereum/pulls/1980/comments"},"review_comment":{"href":"https://api.github.com/repos/ethereum/go-ethereum/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/ethereum/go-ethereum/pulls/1980/commits"},"statuses":{"href":"https://api.github.com/repos/ethereum/go-ethereum/statuses/8a2a755d286c1b623a7f490ff31de232dff2e2cf"}}}}