Mercurial > illumos > s390-betelgeuse
changeset 1949:dea4b2050ea4 onnv_40
6419880 close() hangs running consumer
author | tomee |
---|---|
date | Mon, 08 May 2006 15:30:36 -0700 |
parents | e6ff65bd0519 |
children | 7f3e6f6affa1 |
files | usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/Consumer.java usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/ConsumerListener.java usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/LocalConsumer.java |
diffstat | 3 files changed, 100 insertions(+), 23 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/Consumer.java Mon May 08 12:12:04 2006 -0700 +++ b/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/Consumer.java Mon May 08 15:30:36 2006 -0700 @@ -418,11 +418,51 @@ * @throws IllegalStateException if called before {@link #go()} or * if {@code stop()} was already called * @see #go() + * @see #abort() * @see #close() */ public void stop(); /** + * Aborts the background thread started by {@link #go()}. {@code + * abort()} is effectively the same as {@link #stop()} except that + * it does not block (i.e. it does not wait until the background + * thread actually stops). {@link #isRunning()} is likely {@code + * true} immediately after a call to {@code abort()}, since an + * aborted consumer stops at a time specified as later. + * Specifically, a call to {@code abort()} stops tracing just before + * the next {@link ConsumerListener#intervalBegan(ConsumerEvent e) + * intervalBegan()} event and stops consuming probe data by the + * subsequent {@link ConsumerListener#intervalEnded(ConsumerEvent e) + * intervalEnded()} event. When the aborted consumer actually + * stops, listeners are notified in the {@link + * ConsumerListener#consumerStopped(ConsumerEvent e) + * consumerStopped()} method, where it is convenient to {@link + * #close()} the stopped consumer after requesting the final + * aggregate. + * <p> + * The {@code abort()} and {@code stop()} methods have slightly + * different behavior when called <i>just after</i> {@code go()} but + * <i>before</i> the consumer actually starts running: It is + * possible to {@code stop()} a consumer before it starts running + * (resulting in a {@code consumerStopped()} event without a + * matching {@code consumerStarted()} event), whereas an aborted + * consumer will not stop until after it starts running, when it + * completes a single interval (that interval does not include + * sleeping to wait for traced probe data). Calling {@code abort()} + * before {@code go()} is legal and has the same effect as calling + * it after {@code go()} and before the consumer starts running. + * The last behavior follows from the design: You do not know the + * state of a consumer after calling {@code abort()}, nor is it + * necessary to know the state of a consumer before calling {@code + * abort()}. That may be preferable, for example, when you want to + * abort a consumer opened and started in another thread. + * + * @see #stop() + */ + public void abort(); + + /** * Closes an open consumer and releases the system resources it was * holding. If the consumer is running, {@code close()} will {@link * #stop()} it automatically. A closed consumer cannot be
--- a/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/ConsumerListener.java Mon May 08 12:12:04 2006 -0700 +++ b/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/ConsumerListener.java Mon May 08 15:30:36 2006 -0700 @@ -90,16 +90,17 @@ /** * Called once when the source {@link Consumer} is stopped, * indicating that this listener should expect no further events. - * Called only if there was a prior call to {@link - * #consumerStarted(ConsumerEvent e) consumerStarted()}, that is, - * only if the consumer was successfully started by a call to {@link - * Consumer#go()}. Guaranteed to be called whether the consumer was - * stopped by request (via {@link Consumer#stop()}), terminated - * normally as a result of the DTrace {@code exit()} action or the - * completion of all target processes, or terminated abnormally - * because of an exception. It is necessary to call {@link - * Consumer#close()} to release any system resources still held by - * the stopped consumer. + * Guaranteed to be called whether the consumer was stopped by + * request (by calling {@link Consumer#stop()} or {@link + * Consumer#abort()}), terminated normally as a result of the DTrace + * {@code exit()} action (see <a + * href=http://docs.sun.com/app/docs/doc/817-6223/6mlkidlhm?a=view> + * <tt>exit()</tt></a> in the <b>Special Actions</b> section of the + * <b>Actions and Subroutines</b> chapter of the <i>Solaris Dynamic + * Tracing Guide</i>) or after the completion of all target + * processes, or terminated abnormally because of an exception. It + * is necessary to call {@link Consumer#close()} to release any + * system resources still held by the stopped consumer. * * @see #consumerStarted(ConsumerEvent e) */
--- a/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/LocalConsumer.java Mon May 08 12:12:04 2006 -0700 +++ b/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/LocalConsumer.java Mon May 08 15:30:36 2006 -0700 @@ -746,6 +746,13 @@ t.start(); } + /** + * @inheritDoc + * + * @throws IllegalThreadStateException if attempting to {@code + * stop()} a running consumer while holding the lock on that + * consumer + */ public void stop() { @@ -791,7 +798,7 @@ throw new IllegalStateException( "consumer already stopped"); } - logger.info("consumer already stopped"); + logger.fine("consumer already stopped"); break; case CLOSED: throw new IllegalStateException("consumer closed"); @@ -804,6 +811,12 @@ } if (running) { + if (Thread.holdsLock(this)) { + throw new IllegalThreadStateException("The current " + + "thread cannot stop this LocalConsumer while " + + "holding the lock on this LocalConsumer"); + } + // // Calls no libdtrace methods, so no synchronization is // needed. Sets a native flag that causes the consumer @@ -833,26 +846,49 @@ } } - public synchronized void + public void + abort() + { + _interrupt(); + } + + /** + * @inheritDoc + * + * @throws IllegalThreadStateException if attempting to {@code + * close()} a running consumer while holding the lock on that + * consumer + */ + public void close() { - if ((state == State.INIT) || (state == State.CLOSED)) { - state = State.CLOSED; - return; + synchronized (this) { + if ((state == State.INIT) || (state == State.CLOSED)) { + state = State.CLOSED; + return; + } } - if ((state == State.STARTED) || (state == State.GO)) { + try { stop(); + } catch (IllegalStateException e) { + // ignore (we don't have synchronized state access because + // it is illegal to call stop() while holding the lock on + // this consumer) } - synchronized (LocalConsumer.class) { - _close(); - } - _destroy(); - state = State.CLOSED; + synchronized (this) { + if (state != State.CLOSED) { + synchronized (LocalConsumer.class) { + _close(); + } + _destroy(); + state = State.CLOSED; - if (logger.isLoggable(Level.INFO)) { - logger.info("consumer table count: " + _openCount()); + if (logger.isLoggable(Level.INFO)) { + logger.info("consumer table count: " + _openCount()); + } + } } }