summaryrefslogtreecommitdiff
path: root/jurt
diff options
context:
space:
mode:
authorJens-Heiner Rechtien <hr@openoffice.org>2003-08-07 13:38:15 +0000
committerJens-Heiner Rechtien <hr@openoffice.org>2003-08-07 13:38:15 +0000
commit82cc6f363efae986e51936f4aade6df33d65bfe2 (patch)
tree42a5e0130129c8993d92e8d2623cba8f73cb9ebd /jurt
parent9b345f78fa2605bad6be6762cf5b1ddf9e8f498b (diff)
INTEGRATION: CWS sb5 (1.29.12); FILE MERGED
2003/07/21 09:19:01 sb 1.29.12.2: RESYNC: (1.29-1.30); FILE MERGED 2003/06/23 15:12:11 sb 1.29.12.1: #106808# Fixed synchronization to avoid deadlocks between MessageDispatcher thread and disposed method.
Diffstat (limited to 'jurt')
-rw-r--r--jurt/com/sun/star/lib/uno/bridges/java_remote/java_remote_bridge.java180
1 files changed, 93 insertions, 87 deletions
diff --git a/jurt/com/sun/star/lib/uno/bridges/java_remote/java_remote_bridge.java b/jurt/com/sun/star/lib/uno/bridges/java_remote/java_remote_bridge.java
index 8febd210dd82..bb5352e2c0d1 100644
--- a/jurt/com/sun/star/lib/uno/bridges/java_remote/java_remote_bridge.java
+++ b/jurt/com/sun/star/lib/uno/bridges/java_remote/java_remote_bridge.java
@@ -2,9 +2,9 @@
*
* $RCSfile: java_remote_bridge.java,v $
*
- * $Revision: 1.30 $
+ * $Revision: 1.31 $
*
- * last change: $Author: vg $ $Date: 2003-07-09 09:21:39 $
+ * last change: $Author: hr $ $Date: 2003-08-07 14:38:15 $
*
* The Contents of this file are made available subject to the terms of
* either of the following licenses
@@ -127,7 +127,7 @@ import com.sun.star.uno.Any;
* The protocol to used is passed by name, the bridge
* then looks for it under <code>com.sun.star.lib.uno.protocols</code>.
* <p>
- * @version $Revision: 1.30 $ $ $Date: 2003-07-09 09:21:39 $
+ * @version $Revision: 1.31 $ $ $Date: 2003-08-07 14:38:15 $
* @author Kay Ramme
* @see com.sun.star.lib.uno.environments.remote.IProtocol
* @since UDK1.0
@@ -149,8 +149,6 @@ public class java_remote_bridge
public class MessageDispatcher extends Thread implements IInvokable {
- boolean _quit = false;
-
private ThreadId _threadId;
MessageDispatcher() {
@@ -177,7 +175,13 @@ public class java_remote_bridge
Throwable throwable = null;
try {
- do {
+ for (;;) {
+ synchronized (this) {
+ if (terminate) {
+ break;
+ }
+ }
+
// Use the protocol to read a job.
IMessage iMessage = _iProtocol.readMessage(_inputStream);
@@ -258,10 +262,9 @@ public class java_remote_bridge
iMessage = null;
// this is important to get rid of the job (especially while testing lifecycles)
}
- while(!_quit);
}
catch(EOFException eofException) {
- if(!_quit && DEBUG) {
+ if(DEBUG) {
System.err.println(getClass() + " - reading message - exception occurred: \"" + eofException + "\"");
System.err.println(getClass() + " - giving up");
}
@@ -280,13 +283,18 @@ public class java_remote_bridge
throwable = new DisposedException( exception.getMessage() );
}
- // dispose this bridge only within an error
- if (!_quit) {
- java_remote_bridge.this.dispose(throwable);
- }
+ java_remote_bridge.this.dispose(throwable);
return null;
}
+
+ public synchronized void terminate() {
+ terminate = true;
+ }
+
+ // Variable terminate must only be used while synchronized on this
+ // object:
+ private boolean terminate = false;
}
@@ -678,98 +686,97 @@ public class java_remote_bridge
* <p>
* @see com.sun.star.uno.IBridge#release
*/
- public synchronized void release() {
- -- _life_count;
-
- if(DEBUG) System.err.println("##### " + getClass().getName() + ".release:" + _life_count);
-
- if(_life_count <= 0)
+ public void release() {
+ boolean dispose;
+ synchronized (this) {
+ --_life_count;
+ dispose = _life_count <= 0;
+ }
+ if (dispose) {
dispose(new com.sun.star.uno.RuntimeException("end of life"));
+ }
}
public void dispose() {
dispose(new com.sun.star.uno.RuntimeException("user dispose"));
}
- private synchronized void dispose(Throwable throwable) {
- if(DEBUG) System.err.println("##### " + getClass().getName() + ".dispose - life count:" + _life_count);
-
- if (state == STATE_ALIVE) {
+ private void dispose(Throwable throwable) {
+ synchronized (this) {
+ if (state != STATE_ALIVE) {
+ return;
+ }
state = STATE_DISPOSING;
+ }
- notifyListeners();
- notifyStableListeners();
-
- try {
- // stop the dispatcher thread
- _messageDispatcher._quit = true;
-
- // close the connection
- _xConnection.close();
-
- // interrupt the dispatcher thread, if this thread is not the dispatcher
- if(Thread.currentThread() != _messageDispatcher && _messageDispatcher.isAlive()) {
-
- // THIS IS A ***WORKAROUND*** FOR LINUX SUN JDK1.3 PROBLEM:
- // THE MESSAGEDISPATCHER STAYS IN THE SOCKET READ METHOD,
- // EVEN IF THE SOCKET HAS BEEN CLOSED.
- // SUSPENDING AND RESUMING THE MESSAGEDISPATCHER LETS IT
- // NOTICE THE CLOSED SOCKET
-
- // NOTE!NOTE!NOTE! ONLY USE THIS WORKAROUND FOR LINUX JDK1.3.0
- // NOTE!NOTE!NOTE! FROM SUN OR BLACKDOWN
- // NOTE!NOTE!NOTE! THIS WORKAROUND IS DANGEROUSE AND MAY HARDLOCK
- // NOTE!NOTE!NOTE! THE VM
- if(System.getProperty("os.name", "notlinux").toLowerCase().equals("linux")
- && System.getProperty("java.version", "not1.3").startsWith("1.3.0")
- && (System.getProperty("java.vendor", "notsun").toLowerCase().indexOf("sun") != -1
- || System.getProperty("java.vendor", "notblackdown").toLowerCase().indexOf("blackdown") != -1))
- {
- if(DEBUG) System.err.println("##### " + getClass().getName() + ".dispose - using linux workaround for SUN or BLACKDOWN jdk1.3.0");
- _messageDispatcher.suspend();
- _messageDispatcher.resume();
- }
- else
- if(DEBUG) System.err.println("##### " + getClass().getName() + ".dispose - not using linux workaround");
-
- _messageDispatcher.join(1000); // wait for thread to die
+ notifyListeners();
+ notifyStableListeners();
- if(_messageDispatcher.isAlive()) { // has not died yet, interrupt it
- _messageDispatcher.interrupt();
- _messageDispatcher.join();
- }
+ try {
+ _messageDispatcher.terminate();
+
+ _xConnection.close();
+
+ if (Thread.currentThread() != _messageDispatcher
+ && _messageDispatcher.isAlive())
+ {
+ // This is a workaround for a Linux Sun JDK1.3 problem: The
+ // message dispatcher stays in the socket read method, even if
+ // the socket has been closed. Suspending and resuming the
+ // message dispatcher lets it notice the closed socket. Only
+ // use this workaround for Linux JDK1.3.0 from Sun or Blackdown.
+ // This workaround is dangerouse and may hardlock the VM.
+ if (System.getProperty("os.name", "").toLowerCase().equals(
+ "linux")
+ && System.getProperty("java.version", "").startsWith(
+ "1.3.0")
+ && (System.getProperty("java.vendor", "").toLowerCase().
+ indexOf("sun") != -1
+ || System.getProperty("java.vendor", "").toLowerCase().
+ indexOf("blackdown") != -1))
+ {
+ _messageDispatcher.suspend();
+ _messageDispatcher.resume();
}
- // interrupt all jobs queued by this bridge
- _iThreadPool.dispose(throwable);
-
- // release all outmapped objects
- freeHolders();
-
- // see if life count is zero, if not give a warning
- if(_life_count != 0 && DEBUG)
- System.err.println(getClass().getName() + ".dispose - life count (proxies left):" + _life_count);
+ _messageDispatcher.join(1000);
+ if (_messageDispatcher.isAlive()) {
+ _messageDispatcher.interrupt();
+ _messageDispatcher.join();
+ }
+ }
+ // interrupt all jobs queued by this bridge
+ _iThreadPool.dispose(throwable);
- if(DEBUG)
- _java_environment.list();
+ // release all outmapped objects
+ freeHolders();
+ if (DEBUG) {
+ if (_life_count != 0) {
+ System.err.println(getClass().getName()
+ + ".dispose - life count (proxies left):"
+ + _life_count);
+ }
+ _java_environment.list();
+ }
- // clear members
- _xConnection = null;
- _java_environment = null;
- _messageDispatcher = null;
+ // clear members
+ _xConnection = null;
+ _java_environment = null;
+ _messageDispatcher = null;
- // TODO! Is it intended that state is left as STATE_DISPOSING
- // when an exception is thrown?
+ // TODO! Is it intended that state is left as STATE_DISPOSING when
+ // an exception is thrown?
+ synchronized (this) {
state = STATE_DISPOSED;
}
- catch(InterruptedException interruptedException) {
- System.err.println(getClass().getName() + ".dispose - InterruptedException:" + interruptedException);
- }
- catch(com.sun.star.io.IOException ioException) {
- System.err.println(getClass().getName() + ".dispose - IOException:" + ioException);
- }
+ } catch (InterruptedException e) {
+ System.err.println(getClass().getName()
+ + ".dispose - InterruptedException:" + e);
+ } catch (com.sun.star.io.IOException e) {
+ System.err.println(getClass().getName() + ".dispose - IOException:"
+ + e);
}
}
@@ -836,7 +843,6 @@ public class java_remote_bridge
+ exception + " " + result);
}
- // FIXME checkDisposed called outside of synchronized block
checkDisposed();
try {
@@ -954,7 +960,7 @@ public class java_remote_bridge
}
// This function must only be called while synchronized on this object:
- private void checkDisposed() {
+ private synchronized void checkDisposed() {
if (state == STATE_DISPOSED) {
throw new DisposedException("java_remote_bridge " + this
+ " is disposed");