Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Changes to make Process::Status compatible with MRI #3270

Merged
merged 6 commits into from Jan 7, 2015

Conversation

yorickpeterse
Copy link
Contributor

See #3268 for the issue that led to these changes. Before we merge this I'd like some feedback on this, in particular abotut the renaming of @exitstatus to @status. I don't think there's a way around this, but just in case there's something better for this I'm creating a PR instead of pushing this straight to the master branch.

Yorick Peterse added 4 commits January 4, 2015 17:47
While MRI removes the `new` method from Process::Status we _do_ have this method
(and an initialize method) that perform certain actions worth testing. More
importantly, this way we can ensure that this class can be initialized from C in
a similar fashion to MRI.

See #3268 for more information.
This ensures that the class can be initialized in a similar fashion to MRI
(mainly from C land) while still keeping it compatible with existing Rubinius
code.
MRI stores the status code in an instance variable called "@status" instead of
"@ExitStatus". Due to the lack of a proper API to set this variable people
instead have to resort to setting it via rb_ivar_set() in C. To ensure
compatibility with MRI we sadly also have to name this variable in the same way.

Due to the variable being renamed the method "exitstatus" now has to be manually
defined, instead of just being an attribute reader.

See #3268 for more information.
@yorickpeterse
Copy link
Contributor Author

MRI eventually ends up using this code to extract the status of a Process::Status object: http://rxr.whitequark.org/mri/source/process.c#302

These specs now cover the other arguments of the #initialize method.
Process::Status.new.should be_an_instance_of(Process::Status)
end

it 'initializes Process::Status with a PID' do
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have a question regarding these specs. Initially I wrote them as following:

describe 'Process::Status#initialize' do
  describe 'with a PID' do
    it 'returns the PID when calling #pid' do
      Process::Status.new(42).pid.should == 42
    end
  end

  describe 'with a PID and exit status' do
    before do
      @status = Process::Status.new(42, 1)
    end

    it 'returns the PID when calling #pid' do
      @status.pid.should == 42
    end

    it 'returns the exit status when calling #exitstatus' do
      @status.exitstatus.should == 1
    end
  end

  # ...
end

While this breaks the specs up more nicely and make sure all attributes are set when combined, I can't help but feel that they're getting a bit verbose. Perhaps shared examples would be a solution to this?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's not a lot that would be simpler with shared specs. This type of spec (ie initialize, check initialized) is difficult to simplify. Your approach in the current version of the specs here is fine.

The purpose of the specs is to be correct, clear, consistent, and simple, in that order. A more verbose spec can be all of those at once.

@termsig = termsig
@stopsig = stopsig
end

def exitstatus
return @status
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Style - return not needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, I'm so used to always using an explicit return that it goes automatically.

@sodabrew
Copy link
Contributor

sodabrew commented Jan 4, 2015

MRI appears to store the termsig and stopsig as high bits in status, always masking out the other bits when returning the 8-bit exit code. I think this is more consistent with the Unix standards for exit status.

http://pubs.opengroup.org/onlinepubs/9699919799/functions/wait.html

http://rxr.whitequark.org/mri/source/process.c#087

087 #ifndef WIFEXITED
088 #define WIFEXITED(w)    (((w) & 0xff) == 0)
089 #endif
090 #ifndef WIFSIGNALED
091 #define WIFSIGNALED(w)  (((w) & 0x7f) > 0 && (((w) & 0x7f) < 0x7f))
092 #endif
093 #ifndef WIFSTOPPED
094 #define WIFSTOPPED(w)   (((w) & 0xff) == 0x7f)
095 #endif
096 #ifndef WEXITSTATUS
097 #define WEXITSTATUS(w)  (((w) >> 8) & 0xff)
098 #endif
099 #ifndef WTERMSIG
100 #define WTERMSIG(w)     ((w) & 0x7f)
101 #endif
102 #ifndef WSTOPSIG
103 #define WSTOPSIG        WEXITSTATUS
104 #endif

@sodabrew
Copy link
Contributor

sodabrew commented Jan 5, 2015

Oh - @yorickpeterse interesting about .to_i, it returns all of the bits, whereas the exitstatus method returns only the 8 bit exit.

brixen added a commit that referenced this pull request Jan 7, 2015
Changes to make Process::Status compatible with MRI
@brixen brixen merged commit 56274d3 into master Jan 7, 2015
@yorickpeterse yorickpeterse deleted the process-initialize branch January 7, 2015 16:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants