GitHub PullRequestEvent at 2014-01-22 19:51:41
Repository: ruby
Actor: csfrancis
Payload: {"action":"opened","number":512,"pull_request":{"url":"https://api.github.com/repos/ruby/ruby/pulls/512","id":11772580,"html_url":"https://github.com/ruby/ruby/pull/512","diff_url":"https://github.com/ruby/ruby/pull/512.diff","patch_url":"https://github.com/ruby/ruby/pull/512.patch","issue_url":"https://github.com/ruby/ruby/pull/512","number":512,"state":"open","title":"Fix deadlock in rb_fork_internal","user":{"login":"csfrancis","id":4303686,"avatar_url":"https://gravatar.com/avatar/19292d51ffb2482dc8e747a7f7946261?d=https%3A%2F%2Fidenticons.github.com%2Fa7eb46dd4110f885f9f3722b99cb5855.png&r=x","gravatar_id":"19292d51ffb2482dc8e747a7f7946261","url":"https://api.github.com/users/csfrancis","html_url":"https://github.com/csfrancis","followers_url":"https://api.github.com/users/csfrancis/followers","following_url":"https://api.github.com/users/csfrancis/following{/other_user}","gists_url":"https://api.github.com/users/csfrancis/gists{/gist_id}","starred_url":"https://api.github.com/users/csfrancis/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/csfrancis/subscriptions","organizations_url":"https://api.github.com/users/csfrancis/orgs","repos_url":"https://api.github.com/users/csfrancis/repos","events_url":"https://api.github.com/users/csfrancis/events{/privacy}","received_events_url":"https://api.github.com/users/csfrancis/received_events","type":"User","site_admin":false},"body":"The problem arises when a signal is sent at the same time as a process is being forked via `IO.popen`. In this case, the `recv_child_error` function called by `rb_fork_internal` makes a call to the `read` syscall which returns -1 with errno set to EINTR. Because the child process hasn't actually exited, this effectively deadlocks MRI, as the code in `rb_fork_internal` blocks indefinitely waiting for the child process to exit so that the exit code can be returned to the caller:\r\n\r\n```c\r\n        error_occured = recv_child_error(ep[0], &state, &exc, &err, errmsg, errmsg_buflen, chfunc_is_async_signal_safe);\r\n        if (state || error_occured) {\r\n            if (status) {\r\n                rb_protect(proc_syswait, (VALUE)pid, status);\r\n                if (state) *status = state;\r\n            }\r\n            else {\r\n                rb_syswait(pid);\r\n                if (state) rb_exc_raise(exc);\r\n            }\r\n```\r\n\r\nThe fix is to retry the `read` in `recv_child_error` when errno is `EINTR`. This ensures that we will not incorrectly block waiting for the child process to exit when the parent receives a signal.\r\n\r\nWe were able to reproduce this problem with the following Ruby code:\r\n\r\n```ruby\r\n#!/usr/bin/env ruby\r\n\r\ntrap(\"QUIT\"){}\r\n\r\n1000.times do |i|\r\n  puts \"iteration #{i}\"\r\n  fork do\r\n    Process.kill(\"QUIT\", Process.ppid)\r\n  end\r\n  IO.popen(\"cat\", 'r+'){}\r\nend\r\n```","created_at":"2014-01-22T19:51:40Z","updated_at":"2014-01-22T19:51:40Z","closed_at":null,"merged_at":null,"merge_commit_sha":null,"assignee":null,"milestone":null,"commits_url":"https://github.com/ruby/ruby/pull/512/commits","review_comments_url":"https://github.com/ruby/ruby/pull/512/comments","review_comment_url":"/repos/ruby/ruby/pulls/comments/{number}","comments_url":"https://api.github.com/repos/ruby/ruby/issues/512/comments","statuses_url":"https://api.github.com/repos/ruby/ruby/statuses/dca8e412b8c756358280104fa405d1d179c119a4","head":{"label":"csfrancis:trunk","ref":"trunk","sha":"dca8e412b8c756358280104fa405d1d179c119a4","user":{"login":"csfrancis","id":4303686,"avatar_url":"https://gravatar.com/avatar/19292d51ffb2482dc8e747a7f7946261?d=https%3A%2F%2Fidenticons.github.com%2Fa7eb46dd4110f885f9f3722b99cb5855.png&r=x","gravatar_id":"19292d51ffb2482dc8e747a7f7946261","url":"https://api.github.com/users/csfrancis","html_url":"https://github.com/csfrancis","followers_url":"https://api.github.com/users/csfrancis/followers","following_url":"https://api.github.com/users/csfrancis/following{/other_user}","gists_url":"https://api.github.com/users/csfrancis/gists{/gist_id}","starred_url":"https://api.github.com/users/csfrancis/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/csfrancis/subscriptions","organizations_url":"https://api.github.com/users/csfrancis/orgs","repos_url":"https://api.github.com/users/csfrancis/repos","events_url":"https://api.github.com/users/csfrancis/events{/privacy}","received_events_url":"https://api.github.com/users/csfrancis/received_events","type":"User","site_admin":false},"repo":{"id":16150156,"name":"ruby","full_name":"csfrancis/ruby","owner":{"login":"csfrancis","id":4303686,"avatar_url":"https://gravatar.com/avatar/19292d51ffb2482dc8e747a7f7946261?d=https%3A%2F%2Fidenticons.github.com%2Fa7eb46dd4110f885f9f3722b99cb5855.png&r=x","gravatar_id":"19292d51ffb2482dc8e747a7f7946261","url":"https://api.github.com/users/csfrancis","html_url":"https://github.com/csfrancis","followers_url":"https://api.github.com/users/csfrancis/followers","following_url":"https://api.github.com/users/csfrancis/following{/other_user}","gists_url":"https://api.github.com/users/csfrancis/gists{/gist_id}","starred_url":"https://api.github.com/users/csfrancis/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/csfrancis/subscriptions","organizations_url":"https://api.github.com/users/csfrancis/orgs","repos_url":"https://api.github.com/users/csfrancis/repos","events_url":"https://api.github.com/users/csfrancis/events{/privacy}","received_events_url":"https://api.github.com/users/csfrancis/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/csfrancis/ruby","description":"The Ruby Programming Language","fork":true,"url":"https://api.github.com/repos/csfrancis/ruby","forks_url":"https://api.github.com/repos/csfrancis/ruby/forks","keys_url":"https://api.github.com/repos/csfrancis/ruby/keys{/key_id}","collaborators_url":"https://api.github.com/repos/csfrancis/ruby/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/csfrancis/ruby/teams","hooks_url":"https://api.github.com/repos/csfrancis/ruby/hooks","issue_events_url":"https://api.github.com/repos/csfrancis/ruby/issues/events{/number}","events_url":"https://api.github.com/repos/csfrancis/ruby/events","assignees_url":"https://api.github.com/repos/csfrancis/ruby/assignees{/user}","branches_url":"https://api.github.com/repos/csfrancis/ruby/branches{/branch}","tags_url":"https://api.github.com/repos/csfrancis/ruby/tags","blobs_url":"https://api.github.com/repos/csfrancis/ruby/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/csfrancis/ruby/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/csfrancis/ruby/git/refs{/sha}","trees_url":"https://api.github.com/repos/csfrancis/ruby/git/trees{/sha}","statuses_url":"https://api.github.com/repos/csfrancis/ruby/statuses/{sha}","languages_url":"https://api.github.com/repos/csfrancis/ruby/languages","stargazers_url":"https://api.github.com/repos/csfrancis/ruby/stargazers","contributors_url":"https://api.github.com/repos/csfrancis/ruby/contributors","subscribers_url":"https://api.github.com/repos/csfrancis/ruby/subscribers","subscription_url":"https://api.github.com/repos/csfrancis/ruby/subscription","commits_url":"https://api.github.com/repos/csfrancis/ruby/commits{/sha}","git_commits_url":"https://api.github.com/repos/csfrancis/ruby/git/commits{/sha}","comments_url":"https://api.github.com/repos/csfrancis/ruby/comments{/number}","issue_comment_url":"https://api.github.com/repos/csfrancis/ruby/issues/comments/{number}","contents_url":"https://api.github.com/repos/csfrancis/ruby/contents/{+path}","compare_url":"https://api.github.com/repos/csfrancis/ruby/compare/{base}...{head}","merges_url":"https://api.github.com/repos/csfrancis/ruby/merges","archive_url":"https://api.github.com/repos/csfrancis/ruby/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/csfrancis/ruby/downloads","issues_url":"https://api.github.com/repos/csfrancis/ruby/issues{/number}","pulls_url":"https://api.github.com/repos/csfrancis/ruby/pulls{/number}","milestones_url":"https://api.github.com/repos/csfrancis/ruby/milestones{/number}","notifications_url":"https://api.github.com/repos/csfrancis/ruby/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/csfrancis/ruby/labels{/name}","releases_url":"https://api.github.com/repos/csfrancis/ruby/releases{/id}","created_at":"2014-01-22T19:38:07Z","updated_at":"2014-01-22T19:51:40Z","pushed_at":"2014-01-22T19:45:32Z","git_url":"git://github.com/csfrancis/ruby.git","ssh_url":"git@github.com:csfrancis/ruby.git","clone_url":"https://github.com/csfrancis/ruby.git","svn_url":"https://github.com/csfrancis/ruby","homepage":"http://www.ruby-lang.org/","size":192678,"stargazers_count":0,"watchers_count":0,"language":"Ruby","has_issues":false,"has_downloads":false,"has_wiki":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"trunk","master_branch":"trunk"}},"base":{"label":"ruby:trunk","ref":"trunk","sha":"06d2e8aaf7fe60a09245963f2f69feb5685db8f0","user":{"login":"ruby","id":210414,"avatar_url":"https://gravatar.com/avatar/02cd37c898f360f7bdff82b151f419f3?d=https%3A%2F%2Fidenticons.github.com%2F867592b9286984a3320fd3fb31c2c45c.png&r=x","gravatar_id":"02cd37c898f360f7bdff82b151f419f3","url":"https://api.github.com/users/ruby","html_url":"https://github.com/ruby","followers_url":"https://api.github.com/users/ruby/followers","following_url":"https://api.github.com/users/ruby/following{/other_user}","gists_url":"https://api.github.com/users/ruby/gists{/gist_id}","starred_url":"https://api.github.com/users/ruby/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ruby/subscriptions","organizations_url":"https://api.github.com/users/ruby/orgs","repos_url":"https://api.github.com/users/ruby/repos","events_url":"https://api.github.com/users/ruby/events{/privacy}","received_events_url":"https://api.github.com/users/ruby/received_events","type":"Organization","site_admin":false},"repo":{"id":538746,"name":"ruby","full_name":"ruby/ruby","owner":{"login":"ruby","id":210414,"avatar_url":"https://gravatar.com/avatar/02cd37c898f360f7bdff82b151f419f3?d=https%3A%2F%2Fidenticons.github.com%2F867592b9286984a3320fd3fb31c2c45c.png&r=x","gravatar_id":"02cd37c898f360f7bdff82b151f419f3","url":"https://api.github.com/users/ruby","html_url":"https://github.com/ruby","followers_url":"https://api.github.com/users/ruby/followers","following_url":"https://api.github.com/users/ruby/following{/other_user}","gists_url":"https://api.github.com/users/ruby/gists{/gist_id}","starred_url":"https://api.github.com/users/ruby/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ruby/subscriptions","organizations_url":"https://api.github.com/users/ruby/orgs","repos_url":"https://api.github.com/users/ruby/repos","events_url":"https://api.github.com/users/ruby/events{/privacy}","received_events_url":"https://api.github.com/users/ruby/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/ruby/ruby","description":"The Ruby Programming Language","fork":false,"url":"https://api.github.com/repos/ruby/ruby","forks_url":"https://api.github.com/repos/ruby/ruby/forks","keys_url":"https://api.github.com/repos/ruby/ruby/keys{/key_id}","collaborators_url":"https://api.github.com/repos/ruby/ruby/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/ruby/ruby/teams","hooks_url":"https://api.github.com/repos/ruby/ruby/hooks","issue_events_url":"https://api.github.com/repos/ruby/ruby/issues/events{/number}","events_url":"https://api.github.com/repos/ruby/ruby/events","assignees_url":"https://api.github.com/repos/ruby/ruby/assignees{/user}","branches_url":"https://api.github.com/repos/ruby/ruby/branches{/branch}","tags_url":"https://api.github.com/repos/ruby/ruby/tags","blobs_url":"https://api.github.com/repos/ruby/ruby/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/ruby/ruby/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/ruby/ruby/git/refs{/sha}","trees_url":"https://api.github.com/repos/ruby/ruby/git/trees{/sha}","statuses_url":"https://api.github.com/repos/ruby/ruby/statuses/{sha}","languages_url":"https://api.github.com/repos/ruby/ruby/languages","stargazers_url":"https://api.github.com/repos/ruby/ruby/stargazers","contributors_url":"https://api.github.com/repos/ruby/ruby/contributors","subscribers_url":"https://api.github.com/repos/ruby/ruby/subscribers","subscription_url":"https://api.github.com/repos/ruby/ruby/subscription","commits_url":"https://api.github.com/repos/ruby/ruby/commits{/sha}","git_commits_url":"https://api.github.com/repos/ruby/ruby/git/commits{/sha}","comments_url":"https://api.github.com/repos/ruby/ruby/comments{/number}","issue_comment_url":"https://api.github.com/repos/ruby/ruby/issues/comments/{number}","contents_url":"https://api.github.com/repos/ruby/ruby/contents/{+path}","compare_url":"https://api.github.com/repos/ruby/ruby/compare/{base}...{head}","merges_url":"https://api.github.com/repos/ruby/ruby/merges","archive_url":"https://api.github.com/repos/ruby/ruby/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/ruby/ruby/downloads","issues_url":"https://api.github.com/repos/ruby/ruby/issues{/number}","pulls_url":"https://api.github.com/repos/ruby/ruby/pulls{/number}","milestones_url":"https://api.github.com/repos/ruby/ruby/milestones{/number}","notifications_url":"https://api.github.com/repos/ruby/ruby/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/ruby/ruby/labels{/name}","releases_url":"https://api.github.com/repos/ruby/ruby/releases{/id}","created_at":"2010-02-27T15:55:23Z","updated_at":"2014-01-22T17:43:51Z","pushed_at":"2014-01-22T17:43:51Z","git_url":"git://github.com/ruby/ruby.git","ssh_url":"git@github.com:ruby/ruby.git","clone_url":"https://github.com/ruby/ruby.git","svn_url":"https://github.com/ruby/ruby","homepage":"http://www.ruby-lang.org/","size":193200,"stargazers_count":4836,"watchers_count":4836,"language":"Ruby","has_issues":false,"has_downloads":false,"has_wiki":false,"forks_count":1349,"mirror_url":null,"open_issues_count":34,"forks":1349,"open_issues":34,"watchers":4836,"default_branch":"trunk","master_branch":"trunk"}},"_links":{"self":{"href":"https://api.github.com/repos/ruby/ruby/pulls/512"},"html":{"href":"https://github.com/ruby/ruby/pull/512"},"issue":{"href":"https://api.github.com/repos/ruby/ruby/issues/512"},"comments":{"href":"https://api.github.com/repos/ruby/ruby/issues/512/comments"},"review_comments":{"href":"https://api.github.com/repos/ruby/ruby/pulls/512/comments"},"statuses":{"href":"https://api.github.com/repos/ruby/ruby/statuses/dca8e412b8c756358280104fa405d1d179c119a4"}},"merged":false,"mergeable":null,"mergeable_state":"unknown","merged_by":null,"comments":0,"review_comments":0,"commits":1,"additions":4,"deletions":1,"changed_files":1}}