You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by no...@apache.org on 2010/11/17 12:56:05 UTC

svn commit: r1035990 - in /james/server/trunk: netty-socket/src/main/java/org/jboss/netty/handler/stream/ pop3server/src/main/java/org/apache/james/pop3server/netty/ pop3server/src/test/java/org/apache/james/pop3server/

Author: norman
Date: Wed Nov 17 11:56:05 2010
New Revision: 1035990

URL: http://svn.apache.org/viewvc?rev=1035990&view=rev
Log:
Fix a deadlock which can cause the RETR and TOP command to just hang. This fixed JAMES-1136. Thx to Sylvain Vieujot for reporting

Added:
    james/server/trunk/pop3server/src/main/java/org/apache/james/pop3server/netty/NonWaitingChannelOutputStream.java
      - copied, changed from r1033370, james/server/trunk/pop3server/src/main/java/org/apache/james/pop3server/netty/NonClosingChannelOutputStream.java
Removed:
    james/server/trunk/pop3server/src/main/java/org/apache/james/pop3server/netty/NonClosingChannelOutputStream.java
Modified:
    james/server/trunk/netty-socket/src/main/java/org/jboss/netty/handler/stream/ChannelOutputStream.java
    james/server/trunk/pop3server/src/main/java/org/apache/james/pop3server/netty/POP3NettySession.java
    james/server/trunk/pop3server/src/test/java/org/apache/james/pop3server/AbstractAsyncPOP3ServerTest.java

Modified: james/server/trunk/netty-socket/src/main/java/org/jboss/netty/handler/stream/ChannelOutputStream.java
URL: http://svn.apache.org/viewvc/james/server/trunk/netty-socket/src/main/java/org/jboss/netty/handler/stream/ChannelOutputStream.java?rev=1035990&r1=1035989&r2=1035990&view=diff
==============================================================================
--- james/server/trunk/netty-socket/src/main/java/org/jboss/netty/handler/stream/ChannelOutputStream.java (original)
+++ james/server/trunk/netty-socket/src/main/java/org/jboss/netty/handler/stream/ChannelOutputStream.java Wed Nov 17 11:56:05 2010
@@ -42,6 +42,9 @@ public class ChannelOutputStream extends
         this.channel = channel;
     }
 
+    /**
+     * As this use {@link ChannelFuture#awaitUninterruptibly()} it should not be called from an I/O Thread! If so it will deadlock!
+     */
     @Override
     public void close() throws IOException {
         try {
@@ -75,6 +78,9 @@ public class ChannelOutputStream extends
         write(buf);
     }
 
+    /**
+     * As this use {@link ChannelFuture#awaitUninterruptibly()} it should not be called from an I/O Thread! If so it will deadlock!
+     */
     @Override
     public synchronized void flush() throws IOException {
         if (lastChannelFuture == null) {

Copied: james/server/trunk/pop3server/src/main/java/org/apache/james/pop3server/netty/NonWaitingChannelOutputStream.java (from r1033370, james/server/trunk/pop3server/src/main/java/org/apache/james/pop3server/netty/NonClosingChannelOutputStream.java)
URL: http://svn.apache.org/viewvc/james/server/trunk/pop3server/src/main/java/org/apache/james/pop3server/netty/NonWaitingChannelOutputStream.java?p2=james/server/trunk/pop3server/src/main/java/org/apache/james/pop3server/netty/NonWaitingChannelOutputStream.java&p1=james/server/trunk/pop3server/src/main/java/org/apache/james/pop3server/netty/NonClosingChannelOutputStream.java&r1=1033370&r2=1035990&rev=1035990&view=diff
==============================================================================
--- james/server/trunk/pop3server/src/main/java/org/apache/james/pop3server/netty/NonClosingChannelOutputStream.java (original)
+++ james/server/trunk/pop3server/src/main/java/org/apache/james/pop3server/netty/NonWaitingChannelOutputStream.java Wed Nov 17 11:56:05 2010
@@ -25,22 +25,31 @@ import org.jboss.netty.channel.Channel;
 import org.jboss.netty.handler.stream.ChannelOutputStream;
 
 /**
- * Allow to write via an {@link OutputStream} to the underlying {@link Channel}
+ * Allow to write via an {@link OutputStream} to the underlying {@link Channel}. All writes are just passed to the {@link Channel} without waiting for 
+ * acknowledge. 
  *
  */
-public class NonClosingChannelOutputStream extends ChannelOutputStream{
+public class NonWaitingChannelOutputStream extends ChannelOutputStream{
 
-    public NonClosingChannelOutputStream(Channel channel) {
+    public NonWaitingChannelOutputStream(Channel channel) {
         super(channel);
     }
 
     /**
-     * Just flush the stream. This will NOT close the underlying Channel
+     * This will NOT close the underlying Channel
      * 
      */
     @Override
     public void close() throws IOException {
-        flush();
+        
+    }
+    
+
+    /**
+     * Every write is flushed so this will not do anything
+     */
+    @Override
+    public void flush() throws IOException {
     }
 
 }

Modified: james/server/trunk/pop3server/src/main/java/org/apache/james/pop3server/netty/POP3NettySession.java
URL: http://svn.apache.org/viewvc/james/server/trunk/pop3server/src/main/java/org/apache/james/pop3server/netty/POP3NettySession.java?rev=1035990&r1=1035989&r2=1035990&view=diff
==============================================================================
--- james/server/trunk/pop3server/src/main/java/org/apache/james/pop3server/netty/POP3NettySession.java (original)
+++ james/server/trunk/pop3server/src/main/java/org/apache/james/pop3server/netty/POP3NettySession.java Wed Nov 17 11:56:05 2010
@@ -44,7 +44,7 @@ public class POP3NettySession extends Ab
 
     private MessageManager mailbox;
 
-    private NonClosingChannelOutputStream out;
+    private NonWaitingChannelOutputStream out;
 
     public POP3NettySession(POP3HandlerConfigurationData configData, Log logger, ChannelHandlerContext handlerContext) {
         this(configData, logger, handlerContext, null);
@@ -54,7 +54,7 @@ public class POP3NettySession extends Ab
     public POP3NettySession(POP3HandlerConfigurationData configData, Log logger, ChannelHandlerContext handlerContext, SSLEngine engine) {
         super(logger, handlerContext, engine);
         this.configData = configData;
-        this.out = new NonClosingChannelOutputStream(getChannelHandlerContext().getChannel());
+        this.out = new NonWaitingChannelOutputStream(getChannelHandlerContext().getChannel());
     }
 
 

Modified: james/server/trunk/pop3server/src/test/java/org/apache/james/pop3server/AbstractAsyncPOP3ServerTest.java
URL: http://svn.apache.org/viewvc/james/server/trunk/pop3server/src/test/java/org/apache/james/pop3server/AbstractAsyncPOP3ServerTest.java?rev=1035990&r1=1035989&r2=1035990&view=diff
==============================================================================
--- james/server/trunk/pop3server/src/test/java/org/apache/james/pop3server/AbstractAsyncPOP3ServerTest.java (original)
+++ james/server/trunk/pop3server/src/test/java/org/apache/james/pop3server/AbstractAsyncPOP3ServerTest.java Wed Nov 17 11:56:05 2010
@@ -20,6 +20,7 @@
 package org.apache.james.pop3server;
 
 import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
 import java.io.Reader;
 import java.net.InetAddress;
 import java.net.UnknownHostException;
@@ -66,6 +67,10 @@ public abstract class AbstractAsyncPOP3S
     protected MockFileSystem fSystem;
     protected JamesProtocolHandlerChain chain;
     private InMemoryMailboxManager manager;
+    private byte[] content =        ("Return-path: return@test.com\r\n"+
+            "Content-Transfer-Encoding: plain\r\n"+
+            "Subject: test\r\n\r\n"+
+            "Body Text POP3ServerTest.setupTestMails\r\n").getBytes();
     
     public AbstractAsyncPOP3ServerTest() {
         super("AsyncPOP3ServerTest");
@@ -409,10 +414,7 @@ public abstract class AbstractAsyncPOP3S
     }
 
     private void setupTestMails(MailboxSession session, MessageManager mailbox) throws MessagingException {
-        byte[] content =        ("Return-path: return@test.com\r\n"+
-                                 "Content-Transfer-Encoding: plain\r\n"+
-                                 "Subject: test\r\n\r\n"+
-                                 "Body Text POP3ServerTest.setupTestMails\r\n").getBytes();
+       
         
         mailbox.appendMessage(new ByteArrayInputStream(content), new Date(), session, true, new Flags());
         byte[] content2 = ("EMPTY").getBytes();
@@ -559,4 +561,60 @@ public abstract class AbstractAsyncPOP3S
     }
     */
     
+    
+    // See JAMES-1136
+    public void testDeadlockOnRetr() throws Exception {
+        finishSetUp(m_testConfiguration);
+
+        m_pop3Protocol = new POP3Client();
+        m_pop3Protocol.connect("127.0.0.1",m_pop3ListenerPort);
+
+        m_usersRepository.addUser("foo6", "bar6");
+
+        MailboxPath mailboxPath = MailboxPath.inbox("foo6");
+        MailboxSession session = manager.login("foo6", "bar6", new SimpleLog("Test"));
+        
+        manager.startProcessingRequest(session);
+        if (manager.mailboxExists(mailboxPath, session) == false) {
+            manager.createMailbox(mailboxPath, session);
+        }
+        
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        out.write(content);
+        
+        byte[] bigMail = new byte[1024 * 1024 * 10];
+        int c = 0;
+        for (int i = 0; i < bigMail.length; i++) {
+            
+            bigMail[i] = 'X';
+            c++;
+            if (c == 1000 || i + 3 == bigMail.length) {
+                c = 0;
+                bigMail[++i] = '\r';
+                bigMail[++i] = '\n';
+            }
+        }
+        out.write(bigMail);
+        bigMail = null;
+        
+        manager.getMailbox(mailboxPath, session).appendMessage(new ByteArrayInputStream(out.toByteArray()), new Date(), session, false, new Flags());
+        manager.startProcessingRequest(session);
+        
+        m_pop3Protocol.login("foo6", "bar6");
+        assertEquals(1, m_pop3Protocol.getState());
+
+        POP3MessageInfo[] entries = m_pop3Protocol.listMessages();
+
+        assertNotNull(entries);
+        assertEquals(1, entries.length);
+        assertEquals(1, m_pop3Protocol.getState());
+
+        Reader r = m_pop3Protocol.retrieveMessage(entries[0].number);
+
+        assertNotNull(r);
+        r.close();
+        manager.deleteMailbox(mailboxPath, session);
+        
+    }
+    
 }



---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org