Permalink
Browse files

Avoid perf-damaging extend of WaitReadable and WaitWritable.

In 1.9 mode, SSLErrors are created and then extend either
WaitReadable or WaitWritable if the error reason was that a
nonblocking read or write would block. Because extend changes
class hierarchies and creates new types, performance is impacted.
This patch makes a change similar to EAGAIN readable/writable in
normal IO by creating SSLErrorReadable and SSLErrorWritable that
simply extend SSLError and include the related module exactly
once.
  • Loading branch information...
1 parent 9a1b026 commit 8b022c896ea0d76f876e458229f4f150893295b9 @headius headius committed Nov 18, 2012
@@ -31,6 +31,7 @@
import org.jruby.RubyClass;
import org.jruby.RubyModule;
import org.jruby.exceptions.RaiseException;
+import org.jruby.runtime.builtin.IRubyObject;
/**
* @author <a href="mailto:ola.bini@ki.se">Ola Bini</a>
@@ -61,7 +62,13 @@
public static void createSSL(Ruby runtime, RubyModule ossl) {
RubyModule mSSL = ossl.defineModuleUnder("SSL");
RubyClass openSSLError = ossl.getClass("OpenSSLError");
- mSSL.defineClassUnder("SSLError",openSSLError,openSSLError.getAllocator());
+ RubyClass sslError = mSSL.defineClassUnder("SSLError",openSSLError,openSSLError.getAllocator());
+ if (runtime.is1_9()) {
+ RubyClass sslErrorReadable = mSSL.defineClassUnder("SSLErrorReadable",sslError,openSSLError.getAllocator());
+ sslErrorReadable.include(new IRubyObject[]{runtime.getIO().getConstant("WaitReadable")});
+ RubyClass sslErrorWritable = mSSL.defineClassUnder("SSLErrorWritable",sslError,openSSLError.getAllocator());
+ sslErrorWritable.include(new IRubyObject[]{runtime.getIO().getConstant("WaitWritable")});
+ }
SSLContext.createSSLContext(runtime,mSSL);
SSLSocket.createSSLSocket(runtime,mSSL);
@@ -101,6 +101,14 @@ public static RaiseException newSSLError(Ruby runtime, String message) {
return Utils.newError(runtime, "OpenSSL::SSL::SSLError", message, false);
}
+ public static RaiseException newSSLErrorReadable(Ruby runtime, String message) {
+ return Utils.newError(runtime, "OpenSSL::SSL::SSLErrorReadable", message, false);
+ }
+
+ public static RaiseException newSSLErrorWritable(Ruby runtime, String message) {
+ return Utils.newError(runtime, "OpenSSL::SSL::SSLErrorWritable", message, false);
+ }
+
private org.jruby.ext.openssl.SSLContext rubyCtx;
private SSLEngine engine;
private RubyIO io = null;
@@ -362,16 +370,12 @@ public void wakeup() {
private void readWouldBlock() {
Ruby runtime = getRuntime();
- RaiseException eagain = newSSLError(runtime, "read would block");
- eagain.getException().extend(new IRubyObject[]{runtime.getIO().getConstant("WaitReadable")});
- throw eagain;
+ throw newSSLErrorReadable(runtime, "read would block");
}
private void writeWouldBlock() {
Ruby runtime = getRuntime();
- RaiseException eagain = newSSLError(runtime, "write would block");
- eagain.getException().extend(new IRubyObject[]{runtime.getIO().getConstant("WaitWritable")});
- throw eagain;
+ throw newSSLErrorWritable(runtime, "write would block");
}
private void doHandshake(boolean blocking) throws IOException {
@@ -146,7 +146,7 @@ def test_puts_empty
def test_read_nonblock
ssl_pair {|s1, s2|
err = nil
- assert_raise(OpenSSL::SSL::SSLError) {
+ assert_raise(OpenSSL::SSL::SSLErrorReadable) {
begin
s2.read_nonblock(10)
ensure

0 comments on commit 8b022c8

Please sign in to comment.