From c6d045b330e676ba1f7ba51f489b7c461b72a33a Mon Sep 17 00:00:00 2001 From: Clebert Suconic Date: Wed, 14 Oct 2015 20:55:33 -0400 Subject: [PATCH] ARTEMIS-249 - Improving LibaioContext shutdown This will be avoiding scenarios where you could crash the VM during the LibaioContext.close, if done outside of the proper order. --- .../activemq/artemis/cli/commands/Create.java | 2 +- .../apache/activemq/cli/test/ArtemisTest.java | 8 + artemis-native/bin/libartemis-native-32.so | Bin 22260 -> 26721 bytes artemis-native/bin/libartemis-native-64.so | Bin 21274 -> 23497 bytes ...e_activemq_artemis_jlibaio_LibaioContext.c | 141 +++++++++++--- .../artemis/jlibaio/LibaioContext.java | 46 ++++- .../artemis/jlibaio/test/LibaioTest.java | 13 -- .../jlibaio/test/OpenCloseContextTest.java | 181 ++++++++++++++++++ 8 files changed, 346 insertions(+), 45 deletions(-) create mode 100644 artemis-native/src/test/java/org/apache/activemq/artemis/jlibaio/test/OpenCloseContextTest.java diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Create.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Create.java index 0c558f8010..1de78d96f2 100644 --- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Create.java +++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Create.java @@ -724,7 +724,7 @@ public class Create extends InputAbstract { } } - private boolean supportsLibaio() { + public boolean supportsLibaio() { if (forceLibaio) { // forcing libaio return true; diff --git a/artemis-cli/src/test/java/org/apache/activemq/cli/test/ArtemisTest.java b/artemis-cli/src/test/java/org/apache/activemq/cli/test/ArtemisTest.java index df2ec38e27..c0817907a7 100644 --- a/artemis-cli/src/test/java/org/apache/activemq/cli/test/ArtemisTest.java +++ b/artemis-cli/src/test/java/org/apache/activemq/cli/test/ArtemisTest.java @@ -29,6 +29,7 @@ import org.apache.activemq.artemis.api.core.client.ClientSessionFactory; import org.apache.activemq.artemis.api.core.client.ServerLocator; import org.apache.activemq.artemis.cli.Artemis; import org.apache.activemq.artemis.cli.commands.Configurable; +import org.apache.activemq.artemis.cli.commands.Create; import org.apache.activemq.artemis.cli.commands.Run; import org.apache.activemq.artemis.cli.commands.util.SyncCalculation; import org.apache.activemq.artemis.core.client.impl.ServerLocatorImpl; @@ -77,6 +78,13 @@ public class ArtemisTest { } } + @Test + public void testSupportsLibaio() throws Exception { + Create x = new Create(); + x.setInstance(new File("/tmp/foo")); + x.supportsLibaio(); + } + @Test public void testSync() throws Exception { int writes = 20; diff --git a/artemis-native/bin/libartemis-native-32.so b/artemis-native/bin/libartemis-native-32.so index 15c3d6644a1d385cb425100b138c89417bd4c9ef..540da4b73c2f5c6c371b2b54897f6f6807a2175b 100755 GIT binary patch literal 26721 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≫sD@hkC$fh61Wc<&j56{H+YECPW$2&N^m~9gA7${G_#Q(fO`tdQ)sa~6yM|Ez-p2y8#cKaKb^Lg6bUqxtO z9vkQnC7gaD+hx-8Y)=0?ZT6Eg&}m<%dB18HblNv+-Z$MT=;r;Z_i{P1HU0339Q2)> zK5+l66~XeP{^FUtGdX?We(Fh}D;ci-8&?kc0wKq|zm@izQ+v((vNv-6f&0Fnr`~gERm6iAWn8R?>9dUbgI|9fB8JY-y`Jo3OP#!-Mmj+-`6ad4B#ap-@N~K zkC0>DuRRtEfx+xw#_0q1*DuS#e`^l>iEjt}EJJ(b?fZh?ynlQg9^ee7 ze+8!x-2c8((EI2Ma-;_SpRs2I-Mmjc4~wb6yKyi(wC14Sl7qfM$Ty!S z@C@jK?f2g)_|4}V?8_nlOUZAiM&kJ_;tr*WSZML~o~z?>Uw;I2s@HsOz;e#7^BVu( zorC@;=;ROPb0q%2`HPtO9Dpx!$T#jz;EH!NTXN{3qG=>+ZWwhnEdj8ybKCh>KKAi;MtI5J@s|{IA*frV~TH z@kc*Cf4qa?c}|%2c{i0!om?@EQHHOzsRP&)2R5M7)1#(%d;1Dmk9$rHuV%(P*KD^> zVpNU1@2`bFXX3T|;O+Xprpoi=_hAubzfDAmn#yJYvvVHnl1lh#Q*${er zGyAR`*#~!IpHGr4Vu(8P6EreA&z(+V)kAZHf7VF={U<{Vv1!I*8}!p9vMpvfLxmrR zk)4aa #include #include +#include #include "org_apache_activemq_artemis_jlibaio_LibaioContext.h" #include "exception_helper.h" @@ -53,8 +54,16 @@ struct io_control { int iocbPut; int iocbGet; int used; + }; +// We need a fast and reliable way to stop the blocked poller +// for that we need a dumb file, +// We are using a temporary file for this. +int dumbWriteHandler = 0; +char dumbPath[PATH_MAX]; + + jclass submitClass = NULL; jmethodID errorMethod = NULL; jmethodID doneMethod = NULL; @@ -112,6 +121,20 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved) { if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_6) != JNI_OK) { return JNI_ERR; } else { + + sprintf (dumbPath, "%s/artemisJLHandler_XXXXXX", P_tmpdir); + dumbWriteHandler = mkstemp (dumbPath); + + #ifdef DEBUG + fprintf (stdout, "Creating temp file %s for dumb writes\n", dumbPath); + fflush(stdout); + #endif + + if (dumbWriteHandler < 0) { + fprintf (stderr, "couldn't create stop file handler %s\n", dumbPath); + return JNI_ERR; + } + // // Accordingly to previous experiences we must hold Global Refs on Classes // And @@ -177,12 +200,25 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved) { } } +inline void closeDumbHandlers() { + if (dumbWriteHandler != 0) { + #ifdef DEBUG + fprintf (stdout, "Closing and removing dump handler %s\n", dumbPath); + #endif + dumbWriteHandler = 0; + close(dumbWriteHandler); + unlink(dumbPath); + } +} + void JNI_OnUnload(JavaVM* vm, void* reserved) { JNIEnv* env; if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_6) != JNI_OK) { // Something is wrong but nothing we can do about this :( return; } else { + closeDumbHandlers(); + // delete global references so the GC can collect them if (runtimeExceptionClass != NULL) { (*env)->DeleteGlobalRef(env, runtimeExceptionClass); @@ -201,6 +237,12 @@ void JNI_OnUnload(JavaVM* vm, void* reserved) { } } +JNIEXPORT void JNICALL Java_org_apache_activemq_artemis_jlibaio_LibaioContext_shutdownHook + (JNIEnv * env, jclass clazz) { + closeDumbHandlers(); +} + + static inline struct io_control * getIOControl(JNIEnv* env, jobject pointer) { struct io_control * ioControl = (struct io_control *) (*env)->GetDirectBufferAddress(env, pointer); if (ioControl == NULL) { @@ -252,6 +294,23 @@ static inline void putIOCB(struct io_control * control, struct iocb * iocbBack) pthread_mutex_unlock(&(control->iocbLock)); } +static inline short submit(JNIEnv * env, struct io_control * theControl, struct iocb * iocb) { + int result = io_submit(theControl->ioContext, 1, &iocb); + + if (result < 0) { + // Putting the Global Ref and IOCB back in case of a failure + if (iocb->data != NULL && iocb->data != (void *) -1) { + (*env)->DeleteGlobalRef(env, (jobject)iocb->data); + } + putIOCB(theControl, iocb); + + throwIOExceptionErrorNo(env, "Error while submitting IO: ", -result); + return 0; + } + + return 1; +} + static inline void * getBuffer(JNIEnv* env, jobject pointer) { return (*env)->GetDirectBufferAddress(env, pointer); } @@ -342,12 +401,34 @@ JNIEXPORT void JNICALL Java_org_apache_activemq_artemis_jlibaio_LibaioContext_de return; } - io_queue_release(theControl->ioContext); + struct iocb * iocb = getIOCB(theControl); + + if (iocb == NULL) { + throwIOException(env, "Not enough space in libaio queue"); + return; + } + + // Submitting a dumb write so the loop finishes + io_prep_pwrite(iocb, dumbWriteHandler, 0, 0, 0); + iocb->data = (void *) -1; + if (!submit(env, theControl, iocb)) { + return; + } // to make sure the poll has finished pthread_mutex_lock(&(theControl->pollLock)); pthread_mutex_unlock(&(theControl->pollLock)); + // To return any pending IOCBs + int result = io_getevents(theControl->ioContext, 0, 1, theControl->events, 0); + for (i = 0; i < result; i++) { + struct io_event * event = &(theControl->events[i]); + struct iocb * iocbp = event->obj; + putIOCB(theControl, iocbp); + } + + io_queue_release(theControl->ioContext); + pthread_mutex_destroy(&(theControl->pollLock)); pthread_mutex_destroy(&(theControl->iocbLock)); @@ -389,20 +470,6 @@ JNIEXPORT int JNICALL Java_org_apache_activemq_artemis_jlibaio_LibaioContext_ope return res; } -static inline void submit(JNIEnv * env, struct io_control * theControl, struct iocb * iocb) { - int result = io_submit(theControl->ioContext, 1, &iocb); - - if (result < 0) { - // Putting the Global Ref and IOCB back in case of a failure - (*env)->DeleteGlobalRef(env, (jobject)iocb->data); - putIOCB(theControl, iocb); - - throwIOExceptionErrorNo(env, "Error while submitting IO: ", -result); - } - - return; -} - JNIEXPORT void JNICALL Java_org_apache_activemq_artemis_jlibaio_LibaioContext_submitWrite (JNIEnv * env, jclass clazz, jint fileHandle, jobject contextPointer, jlong position, jint size, jobject bufferWrite, jobject callback) { struct io_control * theControl = getIOControl(env, contextPointer); @@ -429,7 +496,7 @@ JNIEXPORT void JNICALL Java_org_apache_activemq_artemis_jlibaio_LibaioContext_su // also as the real intention is to hold the reference until the life cycle is complete iocb->data = (void *) (*env)->NewGlobalRef(env, callback); - return submit(env, theControl, iocb); + submit(env, theControl, iocb); } JNIEXPORT void JNICALL Java_org_apache_activemq_artemis_jlibaio_LibaioContext_submitRead @@ -454,14 +521,15 @@ JNIEXPORT void JNICALL Java_org_apache_activemq_artemis_jlibaio_LibaioContext_su // also as the real intention is to hold the reference until the life cycle is complete iocb->data = (void *) (*env)->NewGlobalRef(env, callback); - return submit(env, theControl, iocb); + submit(env, theControl, iocb); } JNIEXPORT void JNICALL Java_org_apache_activemq_artemis_jlibaio_LibaioContext_blockedPoll (JNIEnv * env, jobject thisObject, jobject contextPointer) { #ifdef DEBUG - fprintf (stdout, "Running blockedPoll"); + fprintf (stdout, "Running blockedPoll\n"); + fflush(stdout); #endif int i; @@ -472,37 +540,53 @@ JNIEXPORT void JNICALL Java_org_apache_activemq_artemis_jlibaio_LibaioContext_bl int max = theControl->queueSize; pthread_mutex_lock(&(theControl->pollLock)); - for (;;) { + short running = 1; + + while (running) { int result = io_getevents(theControl->ioContext, 1, max, theControl->events, 0); if (result < 0) { - #ifdef DEBUG - fprintf (stdout, "finished blockedPoll rutine with result=%d\n", result); - #endif + throwIOExceptionErrorNo(env, "Error while submitting IO: ", -result); break; } #ifdef DEBUG fprintf (stdout, "blockedPoll returned %d events\n", result); + fflush(stdout); #endif for (i = 0; i < result; i++) { #ifdef DEBUG - fprintf (stdout, "blockedPoll treading event %d\n", i); + fprintf (stdout, "blockedPoll treating event %d\n", i); + fflush(stdout); #endif struct io_event * event = &(theControl->events[i]); struct iocb * iocbp = event->obj; + + if (iocbp->aio_fildes == dumbWriteHandler) { + #ifdef DEBUG + fprintf (stdout, "Dumb write arrived, giving up the loop\n"); + fflush(stdout); + #endif + putIOCB(theControl, iocbp); + running = 0; + break; + } + + int eventResult = (int)event->res; #ifdef DEBUG fprintf (stdout, "Poll res: %d totalRes=%d\n", eventResult, result); + fflush (stdout); #endif if (eventResult < 0) { #ifdef DEBUG fprintf (stdout, "Error: %s\n", strerror(-eventResult)); + fflush (stdout); #endif jstring jstrError = (*env)->NewStringUTF(env, strerror(-eventResult)); @@ -554,14 +638,15 @@ JNIEXPORT jint JNICALL Java_org_apache_activemq_artemis_jlibaio_LibaioContext_po fprintf (stdout, "Error: %s\n", strerror(-eventResult)); #endif - jstring jstrError = (*env)->NewStringUTF(env, strerror(-eventResult)); + if (iocbp->data != NULL && iocbp->data != (void *) -1) { + jstring jstrError = (*env)->NewStringUTF(env, strerror(-eventResult)); - (*env)->CallVoidMethod(env, (jobject)(iocbp->data), errorMethod, (jint)(-eventResult), jstrError); + (*env)->CallVoidMethod(env, (jobject)(iocbp->data), errorMethod, (jint)(-eventResult), jstrError); + } } - (*env)->SetObjectArrayElement(env, callbacks, i, (jobject)iocbp->data); - - if (iocbp->data != NULL) { + if (iocbp->data != NULL && iocbp->data != (void *) -1) { + (*env)->SetObjectArrayElement(env, callbacks, i, (jobject)iocbp->data); // We delete the globalRef after the completion of the callback (*env)->DeleteGlobalRef(env, (jobject)iocbp->data); } diff --git a/artemis-native/src/main/java/org/apache/activemq/artemis/jlibaio/LibaioContext.java b/artemis-native/src/main/java/org/apache/activemq/artemis/jlibaio/LibaioContext.java index 62bd98ffb4..9e86047cc8 100644 --- a/artemis-native/src/main/java/org/apache/activemq/artemis/jlibaio/LibaioContext.java +++ b/artemis-native/src/main/java/org/apache/activemq/artemis/jlibaio/LibaioContext.java @@ -21,7 +21,9 @@ import java.io.File; import java.io.IOException; import java.nio.ByteBuffer; import java.util.concurrent.Semaphore; +import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; import static io.netty.util.internal.ObjectUtil.checkNotNull; @@ -49,10 +51,14 @@ public class LibaioContext implements Closeable { *
* Or else the native module won't be loaded because of version mismatches */ - private static final int EXPECTED_NATIVE_VERSION = 2; + private static final int EXPECTED_NATIVE_VERSION = 3; private static boolean loaded = false; + private static final AtomicBoolean shuttingDown = new AtomicBoolean(false); + + private static final AtomicInteger contexts = new AtomicInteger(0); + public static boolean isLoaded() { return loaded; } @@ -81,6 +87,12 @@ public class LibaioContext implements Closeable { for (String library : libraries) { if (loadLibrary(library)) { loaded = true; + Runtime.getRuntime().addShutdownHook(new Thread() { + public void run() { + shuttingDown.set(true); + checkShutdown(); + } + }); break; } else { @@ -93,6 +105,14 @@ public class LibaioContext implements Closeable { } } + private static void checkShutdown() { + if (contexts.get() == 0 && shuttingDown.get()) { + shutdownHook(); + } + } + + private static native void shutdownHook(); + /** * This is used to validate leaks on tests. * @@ -140,6 +160,7 @@ public class LibaioContext implements Closeable { */ public LibaioContext(int queueSize, boolean useSemaphore) { try { + contexts.incrementAndGet(); this.ioContext = newContext(queueSize); } catch (Exception e) { @@ -170,6 +191,9 @@ public class LibaioContext implements Closeable { int size, ByteBuffer bufferWrite, Callback callback) throws IOException { + if (closed.get()) { + throw new IOException("Libaio Context is closed!"); + } try { if (ioSpace != null) { ioSpace.acquire(); @@ -187,6 +211,9 @@ public class LibaioContext implements Closeable { int size, ByteBuffer bufferWrite, Callback callback) throws IOException { + if (closed.get()) { + throw new IOException("Libaio Context is closed!"); + } try { if (ioSpace != null) { ioSpace.acquire(); @@ -208,11 +235,22 @@ public class LibaioContext implements Closeable { @Override public void close() { if (!closed.getAndSet(true)) { + + if (ioSpace != null) { + try { + ioSpace.tryAcquire(queueSize, 10, TimeUnit.SECONDS); + } + catch (Exception e) { + NativeLogger.LOGGER.error(e); + } + } totalMaxIO.addAndGet(-queueSize); if (ioContext != null) { deleteContext(ioContext); } + contexts.decrementAndGet(); + checkShutdown(); } } @@ -308,17 +346,19 @@ public class LibaioContext implements Closeable { * {@link SubmitInfo#done()} are called. */ public void poll() { - blockedPoll(ioContext); + if (!closed.get()) { + blockedPoll(ioContext); + } } /** * Called from the native layer */ private void done(SubmitInfo info) { + info.done(); if (ioSpace != null) { ioSpace.release(); } - info.done(); } /** diff --git a/artemis-native/src/test/java/org/apache/activemq/artemis/jlibaio/test/LibaioTest.java b/artemis-native/src/test/java/org/apache/activemq/artemis/jlibaio/test/LibaioTest.java index c93670ad85..f9a1aeec02 100644 --- a/artemis-native/src/test/java/org/apache/activemq/artemis/jlibaio/test/LibaioTest.java +++ b/artemis-native/src/test/java/org/apache/activemq/artemis/jlibaio/test/LibaioTest.java @@ -657,19 +657,6 @@ public class LibaioTest { latch.await(); System.out.println("time = " + (end - start) + " writes/second=" + NUMBER_OF_BLOCKS * 1000L / (end - start)); - // - // MultiThreadAsynchronousFileTest.debug((sync ? "Sync result:" : "Async result:") + " Records/Second = " + - // MultiThreadAsynchronousFileTest.NUMBER_OF_THREADS * - // MultiThreadAsynchronousFileTest.NUMBER_OF_LINES * - // 1000 / - // (endTime - startTime) + - // " total time = " + - // (endTime - startTime) + - // " total number of records = " + - // MultiThreadAsynchronousFileTest.NUMBER_OF_THREADS * - // MultiThreadAsynchronousFileTest.NUMBER_OF_LINES); - - Thread.sleep(100); blockedContext.close(); t.join(); diff --git a/artemis-native/src/test/java/org/apache/activemq/artemis/jlibaio/test/OpenCloseContextTest.java b/artemis-native/src/test/java/org/apache/activemq/artemis/jlibaio/test/OpenCloseContextTest.java new file mode 100644 index 0000000000..432c05f014 --- /dev/null +++ b/artemis-native/src/test/java/org/apache/activemq/artemis/jlibaio/test/OpenCloseContextTest.java @@ -0,0 +1,181 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.activemq.artemis.jlibaio.test; + +import java.io.File; +import java.nio.ByteBuffer; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import org.apache.activemq.artemis.jlibaio.LibaioContext; +import org.apache.activemq.artemis.jlibaio.LibaioFile; +import org.apache.activemq.artemis.jlibaio.SubmitInfo; +import org.junit.Assume; +import org.junit.BeforeClass; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; + +public class OpenCloseContextTest { + + @BeforeClass + public static void testAIO() { + Assume.assumeTrue(LibaioContext.isLoaded()); + } + + @Rule + public TemporaryFolder folder; + + public OpenCloseContextTest() { + folder = new TemporaryFolder(new File("./target")); + } + + @Test + public void testRepeatOpenCloseContext() throws Exception { + ByteBuffer buffer = LibaioContext.newAlignedBuffer(512, 512); + for (int i = 0; i < 512; i++) buffer.put((byte)'x'); + + for (int i = 0; i < 10; i++) { + System.out.println("#test " + i); + final LibaioContext control = new LibaioContext<>(5, true); + Thread t = new Thread() { + public void run() { + control.poll(); + } + }; + t.start(); + LibaioFile file = control.openFile(folder.newFile(), true); + file.fill(4 * 1024); + final CountDownLatch insideMethod = new CountDownLatch(1); + final CountDownLatch awaitInside = new CountDownLatch(1); + file.write(0, 512, buffer, new SubmitInfo() { + @Override + public void onError(int errno, String message) { + + } + + @Override + public void done() { + insideMethod.countDown(); + try { + awaitInside.await(); + } + catch (Throwable e) { + e.printStackTrace(); + } + System.out.println("done"); + } + }); + + insideMethod.await(); + + file.write(512, 512, buffer, new SubmitInfo() { + @Override + public void onError(int errno, String message) { + } + + @Override + public void done() { + } + }); + + awaitInside.countDown(); + control.close(); + + + t.join(); + } + + + } + + @Test + public void testRepeatOpenCloseContext2() throws Exception { + ByteBuffer buffer = LibaioContext.newAlignedBuffer(512, 512); + for (int i = 0; i < 512; i++) buffer.put((byte)'x'); + + for (int i = 0; i < 10; i++) { + System.out.println("#test " + i); + final LibaioContext control = new LibaioContext<>(5, true); + Thread t = new Thread() { + public void run() { + control.poll(); + } + }; + t.start(); + LibaioFile file = control.openFile(folder.newFile(), true); + file.fill(4 * 1024); + final CountDownLatch insideMethod = new CountDownLatch(1); + final CountDownLatch awaitInside = new CountDownLatch(1); + file.write(0, 512, buffer, new SubmitInfo() { + @Override + public void onError(int errno, String message) { + + } + + @Override + public void done() { + insideMethod.countDown(); + try { + awaitInside.await(100, TimeUnit.MILLISECONDS); + } + catch (Throwable e) { + e.printStackTrace(); + } + System.out.println("done"); + } + }); + + insideMethod.await(); + + file.write(512, 512, buffer, new SubmitInfo() { + @Override + public void onError(int errno, String message) { + } + + @Override + public void done() { + } + }); + + awaitInside.countDown(); + + control.close(); + + t.join(); + } + + + } + + @Test + public void testCloseAndStart() throws Exception { + final LibaioContext control2 = new LibaioContext<>(5, true); + + final LibaioContext control = new LibaioContext<>(5, true); + control.close(); + control.poll(); + + + control2.close(); + control2.poll(); + + System.out.println("Hello!!"); + } + +}