Skip to content
This repository

Added a Null Object in jeventmachine to prevent exceptions #124

Open
wants to merge 8 commits into from

4 participants

Doug Bradbury Iñaki Baz Castillo Francis Cianfrocca Chris Mowforth
Doug Bradbury

Before eventmachine is initialized or after it's been release, I put in place a Null Object that will prevent "undefined method for nil" errors. This is a fix for issue 123.

Doug Bradbury

Why has this never been touched? Any comments?

Iñaki Baz Castillo
ibc commented

Because EventMachine is unmantained. See #329 (comment).

Francis Cianfrocca
Collaborator
Iñaki Baz Castillo
ibc commented

Hi @garbagecat, Carsten Bormann and me forked the project into EventMachine-LE which includes various ignored pull requests and bug fixes (i.e. real and tested IPv6 support for UDP and TCP client/server). Please consider taking a look to it.

Thanks a lot.

Francis Cianfrocca
Collaborator
Doug Bradbury

@ibc It look like you guys dumped the java reactor though? That's too bad.

Iñaki Baz Castillo

You are right, but the EM Java version was really outdated and does not include lot of changes, features and improvements in the C++ reactor.

Chris Mowforth

@ibc , I'm trying to clear up a few of the JRuby issues in this repo, maybe It'd be better to add the changes to yours though?

Iñaki Baz Castillo

Hi @m0wfo, eventmachine-le has no Java reactor, it was removed because it was considered not updated to the C version.

Chris Mowforth

@ibc Appreciate that- the Java version needs some love. I'm rewriting the original in pure ruby so I'll check back when I have something more concrete.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
4 .gitignore
@@ -14,3 +14,7 @@ Makefile
14 14 *.dSYM
15 15 java/src/.project
16 16 *.rbc
  17 +*.ipr
  18 +*.iml
  19 +*.iws
  20 +.rakeTasks
42 java/src/com/rubyeventmachine/EmReactor.java
@@ -36,8 +36,10 @@
36 36 import java.util.concurrent.atomic.*;
37 37 import java.security.*;
38 38
39   -public class EmReactor {
40   - public final int EM_TIMER_FIRED = 100;
  39 +public class EmReactor implements EmReactorInterface
  40 +{
  41 + private static final NullEventableChannel NULL_EVENTABLE_CHANNEL = new NullEventableChannel();
  42 + public final int EM_TIMER_FIRED = 100;
41 43 public final int EM_CONNECTION_READ = 101;
42 44 public final int EM_CONNECTION_UNBOUND = 102;
43 45 public final int EM_CONNECTION_ACCEPTED = 103;
@@ -126,7 +128,7 @@ void addNewConnections() {
126 128 while (iter2.hasNext()) {
127 129 long b = iter2.next();
128 130
129   - EventableChannel ec = Connections.get(b);
  131 + EventableChannel ec = getConnection(b);
130 132 if (ec != null) {
131 133 try {
132 134 ec.register();
@@ -431,15 +433,25 @@ public long openUdpSocket (String address, int port) throws IOException {
431 433 }
432 434
433 435 public void sendData (long sig, ByteBuffer bb) throws IOException {
434   - Connections.get(sig).scheduleOutboundData( bb );
  436 + getConnection(sig).scheduleOutboundData(bb);
435 437 }
436 438
437   - public void sendData (long sig, byte[] data) throws IOException {
  439 + private EventableChannel getConnection(long sig)
  440 + {
  441 + EventableChannel channel = Connections.get(sig);
  442 + if (channel == null)
  443 + {
  444 + channel = NULL_EVENTABLE_CHANNEL;
  445 + }
  446 + return channel;
  447 + }
  448 +
  449 + public void sendData (long sig, byte[] data) throws IOException {
438 450 sendData (sig, ByteBuffer.wrap(data));
439 451 }
440 452
441 453 public void setCommInactivityTimeout (long sig, long mills) {
442   - Connections.get(sig).setCommInactivityTimeout (mills);
  454 + getConnection(sig).setCommInactivityTimeout(mills);
443 455 }
444 456
445 457 public void sendDatagram (long sig, String data, int length, String recipAddress, int recipPort) {
@@ -447,7 +459,7 @@ public void sendDatagram (long sig, String data, int length, String recipAddress
447 459 }
448 460
449 461 public void sendDatagram (long sig, ByteBuffer bb, String recipAddress, int recipPort) {
450   - (Connections.get(sig)).scheduleOutboundDatagram( bb, recipAddress, recipPort);
  462 + (getConnection(sig)).scheduleOutboundDatagram( bb, recipAddress, recipPort);
451 463 }
452 464
453 465 public long connectTcpServer (String address, int port) {
@@ -494,7 +506,7 @@ public long connectTcpServer (String bindAddr, int bindPort, String address, int
494 506 }
495 507
496 508 public void closeConnection (long sig, boolean afterWriting) {
497   - EventableChannel ec = Connections.get(sig);
  509 + EventableChannel ec = getConnection(sig);
498 510 if (ec != null)
499 511 if (ec.scheduleClose (afterWriting))
500 512 UnboundConnections.add (sig);
@@ -511,7 +523,7 @@ public void signalLoopbreak() {
511 523 }
512 524
513 525 public void startTls (long sig) throws NoSuchAlgorithmException, KeyManagementException {
514   - Connections.get(sig).startTls();
  526 + getConnection(sig).startTls();
515 527 }
516 528
517 529 public void setTimerQuantum (int mills) {
@@ -521,7 +533,7 @@ public void setTimerQuantum (int mills) {
521 533 }
522 534
523 535 public Object[] getPeerName (long sig) {
524   - return Connections.get(sig).getPeerName();
  536 + return getConnection(sig).getPeerName();
525 537 }
526 538
527 539 public long attachChannel (SocketChannel sc, boolean watch_mode) {
@@ -540,7 +552,7 @@ public long attachChannel (SocketChannel sc, boolean watch_mode) {
540 552 }
541 553
542 554 public SocketChannel detachChannel (long sig) {
543   - EventableSocketChannel ec = (EventableSocketChannel) Connections.get (sig);
  555 + EventableSocketChannel ec = (EventableSocketChannel) getConnection(sig);
544 556 if (ec != null) {
545 557 UnboundConnections.add (sig);
546 558 return ec.getChannel();
@@ -550,19 +562,19 @@ public SocketChannel detachChannel (long sig) {
550 562 }
551 563
552 564 public void setNotifyReadable (long sig, boolean mode) {
553   - ((EventableSocketChannel) Connections.get(sig)).setNotifyReadable(mode);
  565 + ((EventableSocketChannel) getConnection(sig)).setNotifyReadable(mode);
554 566 }
555 567
556 568 public void setNotifyWritable (long sig, boolean mode) {
557   - ((EventableSocketChannel) Connections.get(sig)).setNotifyWritable(mode);
  569 + ((EventableSocketChannel) getConnection(sig)).setNotifyWritable(mode);
558 570 }
559 571
560 572 public boolean isNotifyReadable (long sig) {
561   - return Connections.get(sig).isNotifyReadable();
  573 + return getConnection(sig).isNotifyReadable();
562 574 }
563 575
564 576 public boolean isNotifyWritable (long sig) {
565   - return Connections.get(sig).isNotifyWritable();
  577 + return getConnection(sig).isNotifyWritable();
566 578 }
567 579
568 580 public int getConnectionCount() {
70 java/src/com/rubyeventmachine/EmReactorInterface.java
... ... @@ -0,0 +1,70 @@
  1 +package com.rubyeventmachine;
  2 +
  3 +import java.io.IOException;
  4 +import java.net.InetSocketAddress;
  5 +import java.net.SocketAddress;
  6 +import java.nio.ByteBuffer;
  7 +import java.nio.channels.SocketChannel;
  8 +import java.security.KeyManagementException;
  9 +import java.security.NoSuchAlgorithmException;
  10 +
  11 +public interface EmReactorInterface
  12 +{
  13 + void eventCallback (long sig, int eventType, ByteBuffer data, long data2);
  14 +
  15 + void eventCallback (long sig, int eventType, ByteBuffer data);
  16 +
  17 + void run();
  18 +
  19 + void stop();
  20 +
  21 + long installOneshotTimer (int milliseconds);
  22 +
  23 + long startTcpServer (SocketAddress sa) throws EmReactorException;
  24 +
  25 + long startTcpServer (String address, int port) throws EmReactorException;
  26 +
  27 + void stopTcpServer (long signature) throws IOException;
  28 +
  29 + long openUdpSocket (InetSocketAddress address) throws IOException;
  30 +
  31 + long openUdpSocket (String address, int port) throws IOException;
  32 +
  33 + void sendData (long sig, ByteBuffer bb) throws IOException;
  34 +
  35 + void sendData (long sig, byte[] data) throws IOException;
  36 +
  37 + void setCommInactivityTimeout (long sig, long mills);
  38 +
  39 + void sendDatagram (long sig, String data, int length, String recipAddress, int recipPort);
  40 +
  41 + void sendDatagram (long sig, ByteBuffer bb, String recipAddress, int recipPort);
  42 +
  43 + long connectTcpServer (String address, int port);
  44 +
  45 + long connectTcpServer (String bindAddr, int bindPort, String address, int port);
  46 +
  47 + void closeConnection (long sig, boolean afterWriting);
  48 +
  49 + void signalLoopbreak();
  50 +
  51 + void startTls (long sig) throws NoSuchAlgorithmException, KeyManagementException;
  52 +
  53 + void setTimerQuantum (int mills);
  54 +
  55 + Object[] getPeerName (long sig);
  56 +
  57 + long attachChannel (SocketChannel sc, boolean watch_mode);
  58 +
  59 + SocketChannel detachChannel (long sig);
  60 +
  61 + void setNotifyReadable (long sig, boolean mode);
  62 +
  63 + void setNotifyWritable (long sig, boolean mode);
  64 +
  65 + boolean isNotifyReadable (long sig);
  66 +
  67 + boolean isNotifyWritable (long sig);
  68 +
  69 + int getConnectionCount();
  70 +}
157 java/src/com/rubyeventmachine/NullEmReactor.java
... ... @@ -0,0 +1,157 @@
  1 +package com.rubyeventmachine;
  2 +
  3 +import java.io.IOException;
  4 +import java.net.InetSocketAddress;
  5 +import java.net.SocketAddress;
  6 +import java.nio.ByteBuffer;
  7 +import java.nio.channels.SocketChannel;
  8 +import java.security.KeyManagementException;
  9 +import java.security.NoSuchAlgorithmException;
  10 +
  11 +public class NullEmReactor implements EmReactorInterface
  12 +{
  13 + public void eventCallback(long sig, int eventType, ByteBuffer data, long data2)
  14 + {
  15 +
  16 + }
  17 +
  18 + public void eventCallback(long sig, int eventType, ByteBuffer data)
  19 + {
  20 +
  21 + }
  22 +
  23 + public void run()
  24 + {
  25 +
  26 + }
  27 +
  28 + public void stop()
  29 + {
  30 +
  31 + }
  32 +
  33 + public long installOneshotTimer(int milliseconds)
  34 + {
  35 + return 0;
  36 + }
  37 +
  38 + public long startTcpServer(SocketAddress sa) throws EmReactorException
  39 + {
  40 + return 0;
  41 + }
  42 +
  43 + public long startTcpServer(String address, int port) throws EmReactorException
  44 + {
  45 + return 0;
  46 + }
  47 +
  48 + public void stopTcpServer(long signature) throws IOException
  49 + {
  50 +
  51 + }
  52 +
  53 + public long openUdpSocket(InetSocketAddress address) throws IOException
  54 + {
  55 + return 0;
  56 + }
  57 +
  58 + public long openUdpSocket(String address, int port) throws IOException
  59 + {
  60 + return 0;
  61 + }
  62 +
  63 + public void sendData(long sig, ByteBuffer bb) throws IOException
  64 + {
  65 +
  66 + }
  67 +
  68 + public void sendData(long sig, byte[] data) throws IOException
  69 + {
  70 +
  71 + }
  72 +
  73 + public void setCommInactivityTimeout(long sig, long mills)
  74 + {
  75 +
  76 + }
  77 +
  78 + public void sendDatagram(long sig, String data, int length, String recipAddress, int recipPort)
  79 + {
  80 +
  81 + }
  82 +
  83 + public void sendDatagram(long sig, ByteBuffer bb, String recipAddress, int recipPort)
  84 + {
  85 +
  86 + }
  87 +
  88 + public long connectTcpServer(String address, int port)
  89 + {
  90 + return 0;
  91 + }
  92 +
  93 + public long connectTcpServer(String bindAddr, int bindPort, String address, int port)
  94 + {
  95 + return 0;
  96 + }
  97 +
  98 + public void closeConnection(long sig, boolean afterWriting)
  99 + {
  100 +
  101 + }
  102 +
  103 + public void signalLoopbreak()
  104 + {
  105 +
  106 + }
  107 +
  108 + public void startTls(long sig) throws NoSuchAlgorithmException, KeyManagementException
  109 + {
  110 +
  111 + }
  112 +
  113 + public void setTimerQuantum(int mills)
  114 + {
  115 +
  116 + }
  117 +
  118 + public Object[] getPeerName(long sig)
  119 + {
  120 + return new Object[0];
  121 + }
  122 +
  123 + public long attachChannel(SocketChannel sc, boolean watch_mode)
  124 + {
  125 + return 0;
  126 + }
  127 +
  128 + public SocketChannel detachChannel(long sig)
  129 + {
  130 + return null;
  131 + }
  132 +
  133 + public void setNotifyReadable(long sig, boolean mode)
  134 + {
  135 +
  136 + }
  137 +
  138 + public void setNotifyWritable(long sig, boolean mode)
  139 + {
  140 +
  141 + }
  142 +
  143 + public boolean isNotifyReadable(long sig)
  144 + {
  145 + return false;
  146 + }
  147 +
  148 + public boolean isNotifyWritable(long sig)
  149 + {
  150 + return false;
  151 + }
  152 +
  153 + public int getConnectionCount()
  154 + {
  155 + return 0;
  156 + }
  157 +}
74 java/src/com/rubyeventmachine/NullEventableChannel.java
... ... @@ -0,0 +1,74 @@
  1 +package com.rubyeventmachine;
  2 +
  3 +import java.io.IOException;
  4 +import java.nio.ByteBuffer;
  5 +import java.nio.channels.ClosedChannelException;
  6 +
  7 +public class NullEventableChannel implements EventableChannel
  8 +{
  9 + public void scheduleOutboundData(ByteBuffer bb)
  10 + {
  11 +
  12 + }
  13 +
  14 + public void scheduleOutboundDatagram(ByteBuffer bb, String recipAddress, int recipPort)
  15 + {
  16 +
  17 + }
  18 +
  19 + public boolean scheduleClose(boolean afterWriting)
  20 + {
  21 + return false;
  22 + }
  23 +
  24 + public void startTls()
  25 + {
  26 +
  27 + }
  28 +
  29 + public long getBinding()
  30 + {
  31 + return 0;
  32 + }
  33 +
  34 + public void readInboundData(ByteBuffer dst) throws IOException
  35 + {
  36 + }
  37 +
  38 + public void register() throws ClosedChannelException
  39 + {
  40 + }
  41 +
  42 + public void close()
  43 + {
  44 + }
  45 +
  46 + public boolean writeOutboundData() throws IOException
  47 + {
  48 + return false;
  49 + }
  50 +
  51 + public void setCommInactivityTimeout(long seconds)
  52 + {
  53 + }
  54 +
  55 + public Object[] getPeerName()
  56 + {
  57 + return new Object[0];
  58 + }
  59 +
  60 + public boolean isWatchOnly()
  61 + {
  62 + return false;
  63 + }
  64 +
  65 + public boolean isNotifyReadable()
  66 + {
  67 + return false;
  68 + }
  69 +
  70 + public boolean isNotifyWritable()
  71 + {
  72 + return false;
  73 + }
  74 +}
6 lib/jeventmachine.rb
@@ -68,6 +68,8 @@ module EventMachine
68 68 ConnectionNotifyReadable = 106
69 69 ConnectionNotifyWritable = 107
70 70 SslHandshakeCompleted = 108
  71 + NULL_EM_REACTOR = com.rubyeventmachine.NullEmReactor.new
  72 + @em ||= NULL_EM_REACTOR
71 73
72 74 # Exceptions that are defined in rubymain.cpp
73 75 class ConnectionError < RuntimeError; end
@@ -93,7 +95,7 @@ def self.initialize_event_machine
93 95 @em = JEM.new
94 96 end
95 97 def self.release_machine
96   - @em = nil
  98 + @em = NULL_EM_REACTOR
97 99 end
98 100 def self.add_oneshot_timer interval
99 101 @em.installOneshotTimer interval
@@ -256,3 +258,5 @@ def associate_callback_target sig
256 258 end
257 259 end
258 260
  261 +#EventMachine.initialize
  262 +
41 tests/jruby/test_jeventmachine.rb
... ... @@ -0,0 +1,41 @@
  1 +if !(RUBY_PLATFORM =~ /java/)
  2 + puts "Ignorming tests in #{__FILE__}. They must be run in JRuby "
  3 +else
  4 + require 'test/unit'
  5 + require 'jeventmachine'
  6 +
  7 + class TestJEventmachine < Test::Unit::TestCase
  8 +
  9 + def setup
  10 + EventMachine.instance_variable_set("@em", nil)
  11 + load 'jeventmachine.rb'
  12 + end
  13 +
  14 + def test_can_make_calls_without_errors_before_initialization
  15 + assert_equal nil, EventMachine.signal_loopbreak
  16 + assert_equal nil, EventMachine.stop_tcp_server(123)
  17 + assert_equal nil, EventMachine.send_data(123, "rewr", 4)
  18 + assert_equal nil, EventMachine.close_connection(332, nil)
  19 + end
  20 +
  21 + def test_create
  22 + EventMachine::initialize_event_machine
  23 + em = EventMachine::instance_variable_get("@em")
  24 + assert_equal true, em.is_a?(Java::com.rubyeventmachine.EmReactor)
  25 + end
  26 +
  27 + def test_can_make_calls_without_errors_after_release
  28 + EventMachine.initialize_event_machine
  29 + EventMachine.release_machine
  30 +
  31 + assert_equal nil, EventMachine.signal_loopbreak
  32 + assert_equal nil, EventMachine.stop_tcp_server(123)
  33 + assert_equal nil, EventMachine.send_data(123, "rewr", 4)
  34 + assert_equal nil, EventMachine.close_connection(332, nil)
  35 + end
  36 +
  37 +
  38 + end
  39 +end
  40 +
  41 +

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.