Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
[FIXED JENKINS-7809] fixed a race condition in obtaining the tail of …
…the output from remote process.
- Loading branch information
Showing
with
118 additions
and 1 deletion.
@@ -0,0 +1,80 @@ | ||
package hudson; | ||
|
||
import hudson.Launcher.RemoteLauncher; | ||
import hudson.Proc.RemoteProc; | ||
import hudson.remoting.Callable; | ||
import hudson.remoting.Future; | ||
import hudson.remoting.Pipe; | ||
import hudson.remoting.VirtualChannel; | ||
import hudson.slaves.DumbSlave; | ||
import hudson.util.IOUtils; | ||
import hudson.util.StreamTaskListener; | ||
import org.jvnet.hudson.test.Bug; | ||
import org.jvnet.hudson.test.HudsonTestCase; | ||
|
||
import java.io.ByteArrayOutputStream; | ||
import java.io.IOException; | ||
import java.io.OutputStream; | ||
import java.nio.charset.Charset; | ||
|
||
/** | ||
* @author Kohsuke Kawaguchi | ||
*/ | ||
public class ProcTest extends HudsonTestCase { | ||
/** | ||
* Makes sure that the output flushing and {@link RemoteProc#join()} is synced. | ||
*/ | ||
@Bug(7809) | ||
public void testRemoteProcOutputSync() throws Exception { | ||
DumbSlave s = createSlave(); | ||
s.toComputer().connect(false).get(); | ||
VirtualChannel ch=null; | ||
while (ch==null) { | ||
ch = s.toComputer().getChannel(); | ||
Thread.sleep(100); | ||
} | ||
|
||
// keep the pipe fairly busy | ||
final Pipe p = Pipe.createRemoteToLocal(); | ||
for (int i=0; i<10; i++) | ||
ch.callAsync(new ChannelFiller(p.getOut())); | ||
new Thread() { | ||
@Override | ||
public void run() { | ||
try { | ||
IOUtils.drain(p.getIn()); | ||
} catch (IOException e) { | ||
} | ||
} | ||
}.start(); | ||
|
||
RemoteLauncher launcher = new RemoteLauncher(StreamTaskListener.NULL, ch, true); | ||
|
||
String str=""; | ||
for (int i=0; i<256; i++) | ||
str += "oxox"; | ||
|
||
for (int i=0; i<1000; i++) { | ||
ByteArrayOutputStream baos = new ByteArrayOutputStream(); | ||
launcher.launch().cmds("echo",str).stdout(baos).join(); | ||
assertEquals(str, baos.toString().trim()); | ||
} | ||
|
||
ch.close(); | ||
} | ||
|
||
private static class ChannelFiller implements Callable<Void,IOException> { | ||
private final OutputStream o; | ||
|
||
private ChannelFiller(OutputStream o) { | ||
this.o = o; | ||
} | ||
|
||
public Void call() throws IOException { | ||
while (!Thread.interrupted()) { | ||
o.write(new byte[256]); | ||
} | ||
return null; | ||
} | ||
} | ||
} |