Skip to content

Commit 0571351

Browse files
committed
8359477: com/sun/net/httpserver/Test12.java appears to have a temp file race
Reviewed-by: rrich Backport-of: e1681c48287bcce6c8f617d9c0c25354dd62870a
1 parent 078e323 commit 0571351

File tree

2 files changed

+101
-106
lines changed

2 files changed

+101
-106
lines changed

test/jdk/com/sun/net/httpserver/FileServerHandler.java

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -47,7 +47,6 @@ public FileServerHandler (String docroot) {
4747
this.docroot = docroot;
4848
}
4949

50-
int invocation = 1;
5150
public void handle (HttpExchange t)
5251
throws IOException
5352
{
@@ -91,16 +90,16 @@ public void handle (HttpExchange t)
9190
rmap.set ("Content-Type", "text/html");
9291
t.sendResponseHeaders (200, 0);
9392
String[] list = f.list();
94-
OutputStream os = t.getResponseBody();
95-
PrintStream p = new PrintStream (os);
96-
p.println ("<h2>Directory listing for: " + path+ "</h2>");
97-
p.println ("<ul>");
98-
for (int i=0; i<list.length; i++) {
99-
p.println ("<li><a href=\""+list[i]+"\">"+list[i]+"</a></li>");
93+
try (final OutputStream os = t.getResponseBody();
94+
final PrintStream p = new PrintStream (os)) {
95+
p.println("<h2>Directory listing for: " + path + "</h2>");
96+
p.println("<ul>");
97+
for (int i = 0; i < list.length; i++) {
98+
p.println("<li><a href=\"" + list[i] + "\">" + list[i] + "</a></li>");
99+
}
100+
p.println("</ul><p><hr>");
101+
p.flush();
100102
}
101-
p.println ("</ul><p><hr>");
102-
p.flush();
103-
p.close();
104103
} else {
105104
int clen;
106105
if (fixedrequest != null) {
@@ -109,10 +108,9 @@ public void handle (HttpExchange t)
109108
clen = 0;
110109
}
111110
t.sendResponseHeaders (200, clen);
112-
OutputStream os = t.getResponseBody();
113-
FileInputStream fis = new FileInputStream (f);
114111
int count = 0;
115-
try {
112+
try (final OutputStream os = t.getResponseBody();
113+
final FileInputStream fis = new FileInputStream (f)) {
116114
byte[] buf = new byte [16 * 1024];
117115
int len;
118116
while ((len=fis.read (buf)) != -1) {
@@ -122,8 +120,6 @@ public void handle (HttpExchange t)
122120
} catch (IOException e) {
123121
e.printStackTrace();
124122
}
125-
fis.close();
126-
os.close();
127123
}
128124
}
129125

test/jdk/com/sun/net/httpserver/Test12.java

Lines changed: 89 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -21,23 +21,12 @@
2121
* questions.
2222
*/
2323

24-
/*
25-
* @test
26-
* @bug 6270015
27-
* @library /test/lib
28-
* @build jdk.test.lib.Asserts
29-
* jdk.test.lib.Utils
30-
* jdk.test.lib.net.SimpleSSLContext
31-
* jdk.test.lib.net.URIBuilder
32-
* @run main/othervm Test12
33-
* @run main/othervm -Djava.net.preferIPv6Addresses=true Test12
34-
* @summary Light weight HTTP server
35-
*/
36-
3724
import com.sun.net.httpserver.*;
3825

3926
import java.nio.file.Files;
4027
import java.nio.file.Path;
28+
import java.util.ArrayList;
29+
import java.util.List;
4130
import java.util.concurrent.*;
4231
import java.io.*;
4332
import java.net.*;
@@ -49,26 +38,32 @@
4938
import static jdk.test.lib.Asserts.assertFileContentsEqual;
5039
import static jdk.test.lib.Utils.createTempFileOfSize;
5140

52-
/* basic http/s connectivity test
53-
* Tests:
54-
* - same as Test1, but in parallel
41+
/*
42+
* @test
43+
* @bug 6270015 8359477
44+
* @summary Light weight HTTP server - basic http/s connectivity test, same as Test1,
45+
* but in parallel
46+
* @library /test/lib
47+
* @build jdk.test.lib.Asserts
48+
* jdk.test.lib.Utils
49+
* jdk.test.lib.net.SimpleSSLContext
50+
* jdk.test.lib.net.URIBuilder
51+
* @run main/othervm Test12
52+
* @run main/othervm -Djava.net.preferIPv6Addresses=true Test12
5553
*/
56-
5754
public class Test12 extends Test {
5855

5956
private static final String TEMP_FILE_PREFIX =
6057
HttpServer.class.getPackageName() + '-' + Test12.class.getSimpleName() + '-';
6158

6259
static SSLContext ctx;
6360

64-
static boolean fail = false;
65-
6661
public static void main (String[] args) throws Exception {
6762
HttpServer s1 = null;
6863
HttpsServer s2 = null;
69-
ExecutorService executor=null;
7064
Path smallFilePath = createTempFileOfSize(TEMP_FILE_PREFIX, null, 23);
7165
Path largeFilePath = createTempFileOfSize(TEMP_FILE_PREFIX, null, 2730088);
66+
final ExecutorService executor = Executors.newCachedThreadPool();
7267
try {
7368
System.out.print ("Test12: ");
7469
InetAddress loopback = InetAddress.getLoopbackAddress();
@@ -80,7 +75,6 @@ public static void main (String[] args) throws Exception {
8075
HttpHandler h = new FileServerHandler(smallFilePath.getParent().toString());
8176
HttpContext c1 = s1.createContext ("/", h);
8277
HttpContext c2 = s2.createContext ("/", h);
83-
executor = Executors.newCachedThreadPool();
8478
s1.setExecutor (executor);
8579
s2.setExecutor (executor);
8680
ctx = new SimpleSSLContext().get();
@@ -90,7 +84,7 @@ public static void main (String[] args) throws Exception {
9084

9185
int port = s1.getAddress().getPort();
9286
int httpsport = s2.getAddress().getPort();
93-
Runner r[] = new Runner[8];
87+
final Runner[] r = new Runner[8];
9488
r[0] = new Runner (true, "http", port, smallFilePath);
9589
r[1] = new Runner (true, "http", port, largeFilePath);
9690
r[2] = new Runner (true, "https", httpsport, smallFilePath);
@@ -99,95 +93,100 @@ public static void main (String[] args) throws Exception {
9993
r[5] = new Runner (false, "http", port, largeFilePath);
10094
r[6] = new Runner (false, "https", httpsport, smallFilePath);
10195
r[7] = new Runner (false, "https", httpsport, largeFilePath);
102-
start (r);
103-
join (r);
104-
System.out.println ("OK");
96+
// submit the tasks
97+
final List<Future<Void>> futures = new ArrayList<>();
98+
for (Runner runner : r) {
99+
futures.add(executor.submit(runner));
100+
}
101+
// wait for the tasks' completion
102+
for (Future<Void> f : futures) {
103+
f.get();
104+
}
105+
System.out.println ("All " + futures.size() + " tasks completed successfully");
105106
} finally {
106-
if (s1 != null)
107+
if (s1 != null) {
107108
s1.stop(0);
108-
if (s2 != null)
109+
}
110+
if (s2 != null) {
109111
s2.stop(0);
110-
if (executor != null)
111-
executor.shutdown ();
112+
}
113+
boolean terminated = executor.isTerminated();
114+
if (!terminated) {
115+
executor.shutdown();
116+
boolean interrupted = false;
117+
while (!terminated) {
118+
try {
119+
terminated = executor.awaitTermination(1L, TimeUnit.DAYS);
120+
} catch (InterruptedException e) {
121+
if (!interrupted) {
122+
executor.shutdownNow();
123+
interrupted = true;
124+
}
125+
}
126+
}
127+
if (interrupted) {
128+
Thread.currentThread().interrupt();
129+
}
130+
}
131+
// it's OK to delete these files since the server side handlers
132+
// serving these files have completed (guaranteed by the completion of Executor.close())
133+
System.out.println("deleting " + smallFilePath);
112134
Files.delete(smallFilePath);
135+
System.out.println("deleting " + largeFilePath);
113136
Files.delete(largeFilePath);
114137
}
115138
}
116139

117-
static void start (Runner[] x) {
118-
for (int i=0; i<x.length; i++) {
119-
x[i].start();
120-
}
121-
}
122-
123-
static void join (Runner[] x) {
124-
for (int i=0; i<x.length; i++) {
125-
try {
126-
x[i].join();
127-
} catch (InterruptedException e) {}
128-
}
129-
}
130-
131-
132-
static class Runner extends Thread {
140+
static class Runner implements Callable<Void> {
133141

134142
boolean fixedLen;
135143
String protocol;
136144
int port;
137145
private final Path filePath;
138146

139-
Runner (boolean fixedLen, String protocol, int port, Path filePath) {
147+
Runner(boolean fixedLen, String protocol, int port, Path filePath) {
140148
this.fixedLen=fixedLen;
141149
this.protocol=protocol;
142150
this.port=port;
143151
this.filePath = filePath;
144152
}
145153

146-
public void run () {
147-
try {
148-
URL url = URIBuilder.newBuilder()
149-
.scheme(protocol)
150-
.loopback()
151-
.port(port)
152-
.path("/" + filePath.getFileName())
153-
.toURL();
154-
HttpURLConnection urlc = (HttpURLConnection) url.openConnection(Proxy.NO_PROXY);
155-
if (urlc instanceof HttpsURLConnection) {
156-
HttpsURLConnection urlcs = (HttpsURLConnection) urlc;
157-
urlcs.setHostnameVerifier (new HostnameVerifier () {
158-
public boolean verify (String s, SSLSession s1) {
159-
return true;
160-
}
161-
});
162-
urlcs.setSSLSocketFactory (ctx.getSocketFactory());
163-
}
164-
byte [] buf = new byte [4096];
165-
166-
if (fixedLen) {
167-
urlc.setRequestProperty ("XFixed", "yes");
168-
}
169-
InputStream is = urlc.getInputStream();
170-
File temp = File.createTempFile ("Test1", null);
171-
temp.deleteOnExit();
172-
OutputStream fout = new BufferedOutputStream (new FileOutputStream(temp));
173-
int c, count = 0;
174-
while ((c=is.read(buf)) != -1) {
175-
count += c;
176-
fout.write (buf, 0, c);
177-
}
178-
is.close();
179-
fout.close();
180-
181-
if (count != filePath.toFile().length()) {
182-
throw new RuntimeException ("wrong amount of data returned");
183-
}
184-
assertFileContentsEqual(filePath, temp.toPath());
185-
temp.delete();
186-
} catch (Exception e) {
187-
e.printStackTrace();
188-
fail = true;
154+
@Override
155+
public Void call() throws Exception {
156+
final URL url = URIBuilder.newBuilder()
157+
.scheme(protocol)
158+
.loopback()
159+
.port(port)
160+
.path("/" + filePath.getFileName())
161+
.toURL();
162+
final HttpURLConnection urlc = (HttpURLConnection) url.openConnection(Proxy.NO_PROXY);
163+
if (urlc instanceof HttpsURLConnection) {
164+
HttpsURLConnection urlcs = (HttpsURLConnection) urlc;
165+
urlcs.setHostnameVerifier (new HostnameVerifier () {
166+
public boolean verify (String s, SSLSession s1) {
167+
return true;
168+
}
169+
});
170+
urlcs.setSSLSocketFactory (ctx.getSocketFactory());
171+
}
172+
if (fixedLen) {
173+
urlc.setRequestProperty ("XFixed", "yes");
189174
}
175+
final Path temp = Files.createTempFile(Path.of("."), "Test12", null);
176+
final long numReceived;
177+
try (InputStream is = urlc.getInputStream();
178+
OutputStream fout = new BufferedOutputStream(new FileOutputStream(temp.toFile()))) {
179+
numReceived = is.transferTo(fout);
180+
}
181+
System.out.println("received " + numReceived + " response bytes for " + url);
182+
final long expected = filePath.toFile().length();
183+
if (numReceived != expected) {
184+
throw new RuntimeException ("expected " + expected + " bytes, but received "
185+
+ numReceived);
186+
}
187+
assertFileContentsEqual(filePath, temp);
188+
Files.delete(temp);
189+
return null;
190190
}
191191
}
192-
193192
}

0 commit comments

Comments
 (0)