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

[JENKINS-40491] - Improve diagnostincs of the preliminary FifoBuffer termination #138

Merged
merged 1 commit into from
Dec 16, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions src/main/java/org/jenkinsci/remoting/nio/FifoBuffer.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,11 @@
import java.nio.channels.ClosedChannelException;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnegative;
import javax.annotation.concurrent.GuardedBy;
import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.NoExternalUse;

/**
* FIFO buffer for a reader thread and a writer thread to collaborate.
Expand Down Expand Up @@ -167,6 +170,14 @@ public int receive(ReadableByteChannel ch, int max) throws IOException {
*/
@GuardedBy("lock")
private boolean closed;

/**
* Contains the reason why the buffer has been closed.
* The cause also stores the stacktrace of the close command.
*/
@CheckForNull
private CloseCause closeCause;

private boolean closeRequested = false;

public FifoBuffer(int pageSize, int limit) {
Expand Down Expand Up @@ -243,6 +254,16 @@ public boolean isClosed() {
return closed;
}

/**
* Returns Exception with stacktrace of the command, which invoked the buffer close.
* @return Close cause or {@code null}
* @since TODO
*/
@CheckForNull
public CloseCause getCloseCause() {
return closeCause;
}

/**
* Read from this buffer write as much as possible to the channel until
* the channel gets filled up.
Expand Down Expand Up @@ -402,6 +423,7 @@ public void write(byte[] buf, int start, int len) throws InterruptedException, I
public void close() {
// Async modification of the field in order to notify other threads that we are about closing this buffer
closeRequested = true;
closeCause = new CloseCause("Buffer close has been requested");

// Now perform close operation
handleCloseRequest();
Expand Down Expand Up @@ -593,4 +615,21 @@ public int read(byte[] b, int off, int len) throws IOException {
}
};
}

/**
* Explains the reason of the buffer close.
* @since TODO
*/
public static class CloseCause extends Exception {

private static final long serialVersionUID = 1L;

/*package*/ CloseCause(String message) {
super(message);
}

/*package*/ CloseCause(String message, Throwable cause) {
super(message, cause);
}
}
}
11 changes: 7 additions & 4 deletions src/main/java/org/jenkinsci/remoting/nio/NioChannelHub.java
Original file line number Diff line number Diff line change
Expand Up @@ -613,8 +613,10 @@ public void run() {
t.swimLane.submit(new Runnable() {
public void run() {
// if this EOF is unexpected, report an error.
if (!t.getChannel().isInClosed())
t.getChannel().terminate(new EOFException());
if (!t.getChannel().isInClosed()) {
t.getChannel().terminate(new IOException("Unexpected EOF while receiving the data from the channel. "
+ "FIFO buffer has been already closed", t.rb.getCloseCause()));
}
}
});
}
Expand All @@ -628,13 +630,14 @@ public void run() {
}
t.reregister();
} catch (IOException e) {
LOGGER.log(WARNING, "Communication problem", e);
// It causes the channel failure, hence it is severe
LOGGER.log(SEVERE, "Communication problem in " + t + ". NIO Transport will be aborted.", e);
t.abort(e);
} catch (CancelledKeyException e) {
// see JENKINS-24050. I don't understand how this can happen, given that the selector
// thread is the only thread that cancels keys. So to better understand what's going on,
// report the problem.
LOGGER.log(SEVERE, "Unexpected key cancellation for "+t, e);
LOGGER.log(SEVERE, "Unexpected key cancellation for " + t + ". NIO Transport will be aborted.", e);
// to be on the safe side, abort the communication. if we don't do this, it's possible
// that the key never gets re-registered to the selector, and the traffic will hang
// on this channel.
Expand Down