Skip to content
This repository was archived by the owner on Aug 20, 2025. It is now read-only.

Commit 9197c43

Browse files
committed
Store finalizers should not talk to server - bug 7472
1 parent ac05d54 commit 9197c43

8 files changed

Lines changed: 103 additions & 18 deletions

File tree

doc/release/CHANGES.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ K 7356 NPE in Tomcat ClassLoader causes Session.getInstance to fail
3131
K 7378 Deadlock in IMAPFolder.doProtocolCommand()
3232
K 7471 InternetAddress.getLocalAddress should use
3333
InetAddress.getCanonicalHostName
34+
K 7472 Store finalizers should not talk to server
3435

3536

3637
CHANGES IN THE 1.5.5 RELEASE

doc/release/COMPAT.txt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,20 @@ with this release of the JavaMail API.
1616

1717
-- JavaMail 1.5.6 --
1818

19+
- finalizers close sockets abruptly
20+
21+
It's important for finalizers to close an open socket
22+
connection to prevent file descriptor leaks. Previously the
23+
finalizers for the IMAP and POP3 providers would try to close
24+
the connection cleanly, which could result in a timeout waiting
25+
for the server. They now close the connection without
26+
performing any socket I/O, which may result in an unclean
27+
shutdown when seen from the server. Applications should always
28+
close Stores and Folders when done with them to avoid the need
29+
for the finalizer to do this cleanup. The Session property
30+
"mail.<protocol>.finalizecleanclose" can be set to "true" to
31+
force the connection to be closed cleanly in the finalizer.
32+
1933
- InternetAddress.getLocalAddress uses canonical host name
2034

2135
The InternetAddress.getLocalAddress method now uses the

mail/src/main/java/com/sun/mail/imap/IMAPStore.java

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
33
*
4-
* Copyright (c) 1997-2015 Oracle and/or its affiliates. All rights reserved.
4+
* Copyright (c) 1997-2016 Oracle and/or its affiliates. All rights reserved.
55
*
66
* The contents of this file are subject to the terms of either the GNU
77
* General Public License Version 2 only ("GPL") or the Common Development
@@ -225,6 +225,7 @@ public class IMAPStore extends Store
225225
private boolean peek = false;
226226
private boolean closeFoldersOnStoreFailure = true;
227227
private boolean enableCompress = false; // enable COMPRESS=DEFLATE
228+
private boolean finalizeCleanClose = false;
228229

229230
/*
230231
* This field is set in the Store's response handler if we see
@@ -598,6 +599,12 @@ protected IMAPStore(Session session, URLName url,
598599
if (enableCompress)
599600
logger.config("enable COMPRESS");
600601

602+
// check if finalizeCleanClose is enabled
603+
finalizeCleanClose = PropUtil.getBooleanSessionProperty(session,
604+
"mail." + name + ".finalizecleanclose", false);
605+
if (finalizeCleanClose)
606+
logger.config("close connection cleanly in finalize");
607+
601608
s = session.getProperty("mail." + name + ".folder.class");
602609
if (s != null) {
603610
logger.log(Level.CONFIG, "IMAP: folder class: {0}", s);
@@ -1662,6 +1669,14 @@ public synchronized void close() throws MessagingException {
16621669
}
16631670

16641671
protected void finalize() throws Throwable {
1672+
if (!finalizeCleanClose) {
1673+
// when finalizing, close connections abruptly
1674+
synchronized (connectionFailedLock) {
1675+
connectionFailed = true;
1676+
forceClose = true;
1677+
}
1678+
closeFoldersOnStoreFailure = true; // make sure folders get closed
1679+
}
16651680
try {
16661681
close();
16671682
} finally {

mail/src/main/java/com/sun/mail/imap/package.html

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
66
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
77
8-
Copyright (c) 1997-2015 Oracle and/or its affiliates. All rights reserved.
8+
Copyright (c) 1997-2016 Oracle and/or its affiliates. All rights reserved.
99
1010
The contents of this file are subject to the terms of either the GNU
1111
General Public License Version 2 only ("GPL") or the Common Development
@@ -867,6 +867,20 @@ <H4>Properties</H4>
867867
</TD>
868868
</TR>
869869

870+
<A NAME="mail.imap.finalizecleanclose"></A>
871+
<TR id="mail.imap.finalizecleanclose">
872+
<TD>mail.imap.finalizecleanclose</TD>
873+
<TD>boolean</TD>
874+
<TD>
875+
When the finalizer for IMAPStore is called,
876+
should the connection to the server be closed cleanly, as if the
877+
application called the close method?
878+
Or should the connection to the server be closed without sending
879+
any commands to the server?
880+
Defaults to false, the connection is not closed cleanly.
881+
</TD>
882+
</TR>
883+
870884
<A NAME="mail.imap.referralexception"></A>
871885
<TR id="mail.imap.referralexception">
872886
<TD>mail.imap.referralexception</TD>

mail/src/main/java/com/sun/mail/pop3/POP3Folder.java

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
33
*
4-
* Copyright (c) 1997-2015 Oracle and/or its affiliates. All rights reserved.
4+
* Copyright (c) 1997-2016 Oracle and/or its affiliates. All rights reserved.
55
*
66
* The contents of this file are subject to the terms of either the GNU
77
* General Public License Version 2 only ("GPL") or the Common Development
@@ -75,6 +75,7 @@ public class POP3Folder extends Folder {
7575
private POP3Message[] message_cache;
7676
private boolean doneUidl = false;
7777
private volatile TempFile fileCache = null;
78+
private boolean forceClose;
7879

7980
MailLogger logger; // package private, for POP3Message
8081

@@ -250,10 +251,10 @@ public synchronized void close(boolean expunge) throws MessagingException {
250251
* the "marked for deletion" flags. We can then explicitly
251252
* delete messages as desired.
252253
*/
253-
if (store.rsetBeforeQuit)
254+
if (store.rsetBeforeQuit && !forceClose)
254255
port.rset();
255256
POP3Message m;
256-
if (expunge && mode == READ_WRITE) {
257+
if (expunge && mode == READ_WRITE && !forceClose) {
257258
// find all messages marked deleted and issue DELE commands
258259
for (int i = 0; i < message_cache.length; i++) {
259260
if ((m = message_cache[i]) != null) {
@@ -277,7 +278,10 @@ public synchronized void close(boolean expunge) throws MessagingException {
277278
m.invalidate(true);
278279
}
279280

280-
port.quit();
281+
if (forceClose)
282+
port.close();
283+
else
284+
port.quit();
281285
} catch (IOException ex) {
282286
// do nothing
283287
} finally {
@@ -545,11 +549,13 @@ public synchronized InputStream listCommand()
545549
* Close the folder when we're finalized.
546550
*/
547551
protected void finalize() throws Throwable {
552+
forceClose = !store.finalizeCleanClose;
548553
try {
549554
if (opened)
550555
close(false);
551556
} finally {
552557
super.finalize();
558+
forceClose = false;
553559
}
554560
}
555561

mail/src/main/java/com/sun/mail/pop3/POP3Store.java

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
33
*
4-
* Copyright (c) 1997-2015 Oracle and/or its affiliates. All rights reserved.
4+
* Copyright (c) 1997-2016 Oracle and/or its affiliates. All rights reserved.
55
*
66
* The contents of this file are subject to the terms of either the GNU
77
* General Public License Version 2 only ("GPL") or the Common Development
@@ -95,6 +95,7 @@ public class POP3Store extends Store {
9595
volatile boolean useFileCache = false;
9696
volatile File fileCacheDir = null;
9797
volatile boolean keepMessageContent = false;
98+
volatile boolean finalizeCleanClose = false;
9899

99100
public POP3Store(Session session, URLName url) {
100101
this(session, url, "pop3", false);
@@ -136,6 +137,9 @@ public POP3Store(Session session, URLName url,
136137
// mail.pop3.starttls.required requires use of STLS command
137138
requireStartTLS = getBoolProp("starttls.required");
138139

140+
// mail.pop3.finalizecleanclose requires clean close when finalizing
141+
finalizeCleanClose = getBoolProp("finalizecleanclose");
142+
139143
String s = session.getProperty("mail." + name + ".message.class");
140144
if (s != null) {
141145
logger.log(Level.CONFIG, "message class: {0}", s);
@@ -341,9 +345,17 @@ synchronized void closePort(POP3Folder owner) {
341345
}
342346

343347
public synchronized void close() throws MessagingException {
348+
close(false);
349+
}
350+
351+
synchronized void close(boolean force) throws MessagingException {
344352
try {
345-
if (port != null)
346-
port.quit();
353+
if (port != null) {
354+
if (force)
355+
port.close();
356+
else
357+
port.quit();
358+
}
347359
} catch (IOException ioex) {
348360
} finally {
349361
port = null;
@@ -410,7 +422,7 @@ public synchronized boolean isSSL() {
410422
protected void finalize() throws Throwable {
411423
try {
412424
if (port != null) // don't force a connection attempt
413-
close();
425+
close(!finalizeCleanClose);
414426
} finally {
415427
super.finalize();
416428
}

mail/src/main/java/com/sun/mail/pop3/Protocol.java

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -346,17 +346,26 @@ synchronized boolean quit() throws IOException {
346346
Response r = simpleCommand("QUIT");
347347
ok = r.ok;
348348
} finally {
349-
try {
350-
socket.close();
351-
} finally {
352-
socket = null;
353-
input = null;
354-
output = null;
355-
}
349+
close();
356350
}
357351
return ok;
358352
}
359353

354+
/**
355+
* Close the connection without sending any commands.
356+
*/
357+
void close() {
358+
try {
359+
socket.close();
360+
} catch (IOException ex) {
361+
// ignore it
362+
} finally {
363+
socket = null;
364+
input = null;
365+
output = null;
366+
}
367+
}
368+
360369
/**
361370
* Return the total number of messages and mailbox size,
362371
* using the STAT command.

mail/src/main/java/com/sun/mail/pop3/package.html

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
66
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
77
8-
Copyright (c) 1997-2015 Oracle and/or its affiliates. All rights reserved.
8+
Copyright (c) 1997-2016 Oracle and/or its affiliates. All rights reserved.
99
1010
The contents of this file are subject to the terms of either the GNU
1111
General Public License Version 2 only ("GPL") or the Common Development
@@ -606,6 +606,20 @@ <H4>Properties</H4>
606606
</TD>
607607
</TR>
608608

609+
<A NAME="mail.pop3.finalizecleanclose"></A>
610+
<TR id="mail.pop3.finalizecleanclose">
611+
<TD>mail.pop3.finalizecleanclose</TD>
612+
<TD>boolean</TD>
613+
<TD>
614+
When the finalizer for POP3Store or POP3Folder is called,
615+
should the connection to the server be closed cleanly, as if the
616+
application called the close method?
617+
Or should the connection to the server be closed without sending
618+
any commands to the server?
619+
Defaults to false, the connection is not closed cleanly.
620+
</TD>
621+
</TR>
622+
609623
</TABLE>
610624
<P>
611625
In general, applications should not need to use the classes in this

0 commit comments

Comments
 (0)