Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 370850

Summary: Build job gets stuck after being cancelled.
Product: [Tools] CDT Reporter: Alain Lee <a-lee>
Component: cdt-buildAssignee: Project Inbox <cdt-core-inbox>
Status: NEW --- QA Contact: Jonah Graham <jonah>
Severity: normal    
Priority: P3 CC: cdtdoug
Version: 8.0   
Target Milestone: ---   
Hardware: PC   
OS: Windows 7   
Whiteboard:

Description Alain Lee CLA 2012-02-07 11:10:37 EST
Build Identifier: 5.3.1.201109151620

This is very difficult to reproduce. While the project was being built, I clicked the cancel button in the progress window as soon as I saw the message "Finished building xxx.c" displayed on the console. The Build job got stuck and the stop button was already greyed out. The job never got stopped or finished. Hence, other jobs waiting in the background could not stuck. This is the stack trace I captured:

Thread [Worker-11] (Suspended)	
	Object.wait(long) line: not available [native method]	
	ProcessClosure$ReaderThread(Object).wait() line: not available	
	ProcessClosure$ReaderThread.waitFor() line: 84	
	ProcessClosure.terminate() line: 222	
	CCSGmakeLauncher(CommandLauncher).waitAndRead(OutputStream, OutputStream, IProgressMonitor) line: 203	


Reproducible: Sometimes

Steps to Reproduce:
1. Create a project and build it. 
2. While the project was being built, I clicked the cancel button in the progress window as soon as I saw the message "Finished building xxx.c" displayed on the console. 
3. The Build job got stuck and the stop button was already greyed out. The job never got stopped or finished. Hence, other jobs waiting in the background could not stuck.
Comment 1 Alain Lee CLA 2012-02-21 16:55:15 EST
After further investigation, I found the following:

1. Even though ProcessClosure.terminate() was invoked to execute fProcess.destroy(), Windows Task Manager showed gmake.exe was still running. It seemed that gmake got stuck as it never finished.

2. ProcessClosure got stuck in the OutputReader and ErrorReader threads. See below for the stack trace.

Daemon Thread [ErrorReader] (Suspended)	
	owns: InputStreamReader  (id=218)	
	SpawnerInputStream.read0(int, byte[], int) line: not available [native method]	
	SpawnerInputStream.read(byte[], int, int) line: 66	
	StreamDecoder$CharsetSD.readBytes() line: not available	
	StreamDecoder$CharsetSD.implRead(char[], int, int) line: not available	
	StreamDecoder$CharsetSD(StreamDecoder).read(char[], int, int) line: not available	
	InputStreamReader.read(char[], int, int) line: not available	
	BufferedReader.fill() line: not available	
	BufferedReader.readLine(boolean) line: not available	
	BufferedReader.readLine() line: not available	
	ProcessClosure$ReaderThread.run() line: 53	

Daemon Thread [OutputReader] (Suspended)	
	owns: InputStreamReader  (id=224)	
	SpawnerInputStream.read0(int, byte[], int) line: not available [native method]	
	SpawnerInputStream.read(byte[], int, int) line: 66	
	StreamDecoder$CharsetSD.readBytes() line: not available	
	StreamDecoder$CharsetSD.implRead(char[], int, int) line: not available	
	StreamDecoder$CharsetSD(StreamDecoder).read(char[], int, int) line: not available	
	InputStreamReader.read(char[], int, int) line: not available	
	BufferedReader.fill() line: not available	
	BufferedReader.readLine(boolean) line: not available	
	BufferedReader.readLine() line: not available	
	ProcessClosure$ReaderThread.run() line: 53
Comment 2 Alain Lee CLA 2012-02-21 17:08:24 EST
I found the following way to reproduce this problem:

1. In org.eclipse.cdt.internal.core.ProcessClosure.ReaderThread.run(), add the following breakpoints marked by 1>>> and 2>>>:

       public void run() {
           try {
               try {
                   BufferedReader reader = new BufferedReader(new InputStreamReader(fInputStream));
                   String line;
1>>>               while ((line = reader.readLine()) != null) {
                       line += lineSeparator;
                       fOutputStream.write(line.getBytes());
                   }
               } catch (IOException x) {
                   // ignore
               } finally {
                   try {
                       // writer.flush();
2>>>                   fOutputStream.flush();
                   } catch (IOException e) {
                       // ignore
                   }
                   try {
                       fInputStream.close();
                   } catch (IOException e) {
                       // ignore
                   }
               }
           } finally {
               complete();
           }
       }

2. Build a project (preferrably a big project).
3. When the code stops at the breakpoint 1>>> in both the OutputReader and ErrorReader threads, cancel the build job via the progress dialog.
4. In the OutputReader and ErrorReader threads, disable the breakpoint 1>>> and let the code run.
5. The code never reaches the breakpoint 2>>>. 
6. Pause the OutputReader and ErrorReader threads. The code should be waiting at reader.readLine().
7. Windows Task Manager shows that gmake.exe is still running.