From f40f665db811f7686dd61d32c1e7c140ab35d78a Mon Sep 17 00:00:00 2001 From: Jason Feng Date: Sat, 18 Mar 2023 18:24:14 -0400 Subject: [PATCH] zOS AttachAPI doesn't use FileLockWatchdogTask for CommonControlFiles Added a system property com.ibm.tools.attach.useFileLockWatchdog; Setting -Dcom.ibm.tools.attach.useFileLockWatchdog=[true|false] takes precedence, if no such system property is specified, always set false on z/OS, defaults to true on non-z/OS platforms. Signed-off-by: Jason Feng --- .../tools/attach/target/CommonDirectory.java | 8 +-- .../tools/attach/target/FileLock.java | 55 +++++++++++-------- .../internal/tools/attach/target/IPC.java | 26 ++++++++- .../tools/attach/target/WaitLoop.java | 4 +- .../attach/attacher/OpenJ9VirtualMachine.java | 3 +- .../openj9/test/fileLock/NativeFileLock.java | 5 +- 6 files changed, 65 insertions(+), 36 deletions(-) diff --git a/jcl/src/java.base/share/classes/openj9/internal/tools/attach/target/CommonDirectory.java b/jcl/src/java.base/share/classes/openj9/internal/tools/attach/target/CommonDirectory.java index abbf1e51475..e728a3007d7 100644 --- a/jcl/src/java.base/share/classes/openj9/internal/tools/attach/target/CommonDirectory.java +++ b/jcl/src/java.base/share/classes/openj9/internal/tools/attach/target/CommonDirectory.java @@ -1,4 +1,4 @@ -/*[INCLUDE-IF Sidecar18-SE]*/ +/*[INCLUDE-IF JAVA_SPEC_VERSION >= 8]*/ /******************************************************************************* * Copyright IBM Corp. and others 2009 * @@ -150,7 +150,7 @@ public static void obtainControllerLock(String callSite) throws IOException { } } if (null != controllerLockCopy) { /* first entry */ - controllerLockCopy.lockFile(true, callSite + "_obtainControllerLock"); //$NON-NLS-1$ + controllerLockCopy.lockFile(true, callSite + "_obtainControllerLock", IPC.useFileLockWatchdog); //$NON-NLS-1$ } } @@ -166,7 +166,7 @@ static boolean tryObtainControllerLock(String callSite) { ++controllerLockCount; /* optimistically assume we enter the lock */ if (1 == controllerLockCount) { /* first time in */ try { - controllerLockEntered = getControllerLock().lockFile(false, callSite + "_tryObtainControllerLock"); //$NON-NLS-1$ + controllerLockEntered = getControllerLock().lockFile(false, callSite + "_tryObtainControllerLock", IPC.useFileLockWatchdog); //$NON-NLS-1$ if (!controllerLockEntered) { /* lock failed, so revert */ --controllerLockCount; } @@ -205,7 +205,7 @@ public static void releaseControllerLock(String callSite) { */ public static void obtainAttachLock(String callSite) throws IOException { - getAttachLock().lockFile(true, callSite + "_obtainAttachLock"); //$NON-NLS-1$ + getAttachLock().lockFile(true, callSite + "_obtainAttachLock", IPC.useFileLockWatchdog); //$NON-NLS-1$ } /** diff --git a/jcl/src/java.base/share/classes/openj9/internal/tools/attach/target/FileLock.java b/jcl/src/java.base/share/classes/openj9/internal/tools/attach/target/FileLock.java index 395d9c3d7b7..c4eeee8d37c 100644 --- a/jcl/src/java.base/share/classes/openj9/internal/tools/attach/target/FileLock.java +++ b/jcl/src/java.base/share/classes/openj9/internal/tools/attach/target/FileLock.java @@ -61,12 +61,14 @@ public FileLock(String filePath, int mode) { * locks a file using the J9 port library functions. * @param blocking if true, the function waits until the it obtains the file lock or times out. * @param callSite caller info + * @param useWatchdog use FileLockWatchdogTask or not * @return true is file lock obtained. * @throws IOException if the file is already locked. * @note locking and unlocking must be done by the same thread. */ - public boolean lockFile(boolean blocking, String callSite) throws IOException { - String lockFileMsg = blocking ? "locking file ": "non-blocking locking file "; //$NON-NLS-1$//$NON-NLS-2$ + public boolean lockFile(boolean blocking, String callSite, boolean useWatchdog) throws IOException { + String lockFileMsg = (blocking ? "locking file " : "non-blocking locking file ") //$NON-NLS-1$//$NON-NLS-2$ + + (useWatchdog ? "using watchdog" : "NOT using watchdog"); //$NON-NLS-1$//$NON-NLS-2$ IPC.logMessage(callSite + " : " + lockFileMsg, lockFilepath); //$NON-NLS-1$ final int FILE_LOCK_TIMEOUT = 20 * 1000; /* time in milliseconds */ @@ -80,26 +82,29 @@ public boolean lockFile(boolean blocking, String callSite) throws IOException { locked = (0 <= fileDescriptor); /* negative values indicate error, non-negative values (including 0) are valid FDs */ if (!locked && blocking) { /* try again, this time with a blocking lock and a timeout */ - FileLockWatchdogTask wdog = new FileLockWatchdogTask(); + FileLockWatchdogTask wdog = null; IPC.logMessage("lock failed, trying blocking lock, fileDescriptor = " + fileDescriptor); //$NON-NLS-1$ - synchronized (shutdownSync) { /* shutdown is called from a different thread */ - /*[PR Jazz 30075] inlined createFileLockWatchdogTimer*/ - if (!terminated && (null == fileLockWatchdogTimer)) { - fileLockWatchdogTimer = new FilelockTimer("file lock watchdog"); //$NON-NLS-1$ - } - if (null != fileLockWatchdogTimer) { /* check if the VM is shutting down */ - /* - * The file lock timeout is to recover from pathological conditions such as a hung process which is holding the file lock. - * Under this condition, the process will break the lock. - * This timeout affects only the operation of the attach API. It may delay the start of the attach API (but will not affect - * other aspects of the VM or application launch) or delay an attach attempt. It will not delay the VM or attach API shutdown. - */ - IPC.logMessage("FileLock.lockFile() FILE_LOCK_TIMEOUT = " + FILE_LOCK_TIMEOUT, new Throwable("")); //$NON-NLS-1$ //$NON-NLS-2$ - fileLockWatchdogTimer.schedule(wdog, FILE_LOCK_TIMEOUT); - } - else { - IPC.logMessage("FileLock.lockFile() returns false."); //$NON-NLS-1$ - return false; + if (useWatchdog) { + wdog = new FileLockWatchdogTask(); + synchronized (shutdownSync) { /* shutdown is called from a different thread */ + /*[PR Jazz 30075] inlined createFileLockWatchdogTimer*/ + if (!terminated && (null == fileLockWatchdogTimer)) { + fileLockWatchdogTimer = new FilelockTimer("file lock watchdog"); //$NON-NLS-1$ + } + if (null != fileLockWatchdogTimer) { /* check if the VM is shutting down */ + /* + * The file lock timeout is to recover from pathological conditions such as a hung process which is holding the file lock. + * Under this condition, the process will break the lock. + * This timeout affects only the operation of the attach API. It may delay the start of the attach API (but will not affect + * other aspects of the VM or application launch) or delay an attach attempt. It will not delay the VM or attach API shutdown. + */ + IPC.logMessage("FileLock.lockFile() FILE_LOCK_TIMEOUT = " + FILE_LOCK_TIMEOUT, new Throwable("")); //$NON-NLS-1$ //$NON-NLS-2$ + fileLockWatchdogTimer.schedule(wdog, FILE_LOCK_TIMEOUT); + } + else { + IPC.logMessage("FileLock.lockFile() returns false."); //$NON-NLS-1$ + return false; + } } } @@ -116,9 +121,11 @@ public boolean lockFile(boolean blocking, String callSite) throws IOException { unlockFile("lockFile_IOException"); //$NON-NLS-1$ IPC.logMessage("FileLock.lockFile() blocking lock failed with lockFilepath = " + lockFilepath + ", exception message: " + e.getMessage()); //$NON-NLS-1$ //$NON-NLS-2$ } - synchronized (shutdownSync) { - if (null != fileLockWatchdogTimer) { - wdog.cancel(); + if (useWatchdog) { + synchronized (shutdownSync) { + if (null != fileLockWatchdogTimer) { + wdog.cancel(); + } } } } else { diff --git a/jcl/src/java.base/share/classes/openj9/internal/tools/attach/target/IPC.java b/jcl/src/java.base/share/classes/openj9/internal/tools/attach/target/IPC.java index 00c933930e9..175772ee8d0 100644 --- a/jcl/src/java.base/share/classes/openj9/internal/tools/attach/target/IPC.java +++ b/jcl/src/java.base/share/classes/openj9/internal/tools/attach/target/IPC.java @@ -1,4 +1,4 @@ -/*[INCLUDE-IF Sidecar18-SE]*/ +/*[INCLUDE-IF JAVA_SPEC_VERSION >= 8]*/ /******************************************************************************* * Copyright IBM Corp. and others 2009 * @@ -22,6 +22,8 @@ *******************************************************************************/ package openj9.internal.tools.attach.target; +import com.ibm.oti.vm.VM; + import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; @@ -53,6 +55,7 @@ public class IPC { private static final String JAVA_IO_TMPDIR = "java.io.tmpdir"; //$NON-NLS-1$ + private static final String COM_IBM_TOOLS_ATTACH_USE_FILELOCK_WATCHDOG = "com.ibm.tools.attach.useFileLockWatchdog"; //$NON-NLS-1$ /** * Successful return code from natives. */ @@ -85,8 +88,17 @@ public class IPC { */ public static final boolean isZOS; + /** + * Controls use of the FileLockWatchdogTask. + * Setting -Dcom.ibm.tools.attach.useFileLockWatchdog=[true|false] takes + * precedence, if no such system property is specified, always set false on + * z/OS, defaults to true on non-z/OS platforms. + */ + public static final boolean useFileLockWatchdog; + static { - String osName = com.ibm.oti.vm.VM.getVMLangAccess().internalGetProperties().getProperty("os.name"); //$NON-NLS-1$ + Properties props = VM.getVMLangAccess().internalGetProperties(); + String osName = props.getProperty("os.name"); //$NON-NLS-1$ boolean tempIsZos = false; boolean tempIsWindows = false; if (null != osName) { @@ -98,6 +110,14 @@ public class IPC { } isZOS = tempIsZos; isWindows = tempIsWindows; + + String propUseFileLockWatchdog = props.getProperty(COM_IBM_TOOLS_ATTACH_USE_FILELOCK_WATCHDOG); + if (propUseFileLockWatchdog == null) { + // no system property com.ibm.tools.attach.useFileLockWatchdog is specified + useFileLockWatchdog = !isZOS; + } else { + useFileLockWatchdog = "true".equalsIgnoreCase(propUseFileLockWatchdog); + } } private static Random randomGen; /* Cleanup. this is used by multiple threads */ @@ -325,7 +345,7 @@ static String getTmpDir() { String tmpDir = getTempDirImpl(); if (null == tmpDir) { logMessage("Could not get system temporary directory. Trying " + JAVA_IO_TMPDIR); //$NON-NLS-1$ - tmpDir = com.ibm.oti.vm.VM.getVMLangAccess().internalGetProperties().getProperty(JAVA_IO_TMPDIR); + tmpDir = VM.getVMLangAccess().internalGetProperties().getProperty(JAVA_IO_TMPDIR); } return tmpDir; } diff --git a/jcl/src/java.base/share/classes/openj9/internal/tools/attach/target/WaitLoop.java b/jcl/src/java.base/share/classes/openj9/internal/tools/attach/target/WaitLoop.java index a8a5d21bcdd..206bbbe730c 100644 --- a/jcl/src/java.base/share/classes/openj9/internal/tools/attach/target/WaitLoop.java +++ b/jcl/src/java.base/share/classes/openj9/internal/tools/attach/target/WaitLoop.java @@ -133,8 +133,8 @@ private static Attachment checkReplyAndCreateAttachment() throws IOException { if (LOGGING_DISABLED != loggingStatus) { IPC.logMessage("checkReplyAndCreateAttachment iteration "+ AttachHandler.notificationCount+" waitForNotification obtainLock"); //$NON-NLS-1$ //$NON-NLS-2$ } - /* the sync file is missing. */ - if (!AttachHandler.mainHandler.syncFileLock.lockFile(true, "WaitLoop.checkReplyAndCreateAttachment")) { //$NON-NLS-1$ + /* the sync file is missing, use FileLockWatchdogTask for non-CommonControlFile */ + if (!AttachHandler.mainHandler.syncFileLock.lockFile(true, "WaitLoop.checkReplyAndCreateAttachment", true)) { //$NON-NLS-1$ TargetDirectory.createMySyncFile(); /* don't bother locking this since the attacher will not have locked it. */ } else { diff --git a/jcl/src/jdk.attach/share/classes/com/ibm/tools/attach/attacher/OpenJ9VirtualMachine.java b/jcl/src/jdk.attach/share/classes/com/ibm/tools/attach/attacher/OpenJ9VirtualMachine.java index bbd5ea420d3..f1779a2bccb 100644 --- a/jcl/src/jdk.attach/share/classes/com/ibm/tools/attach/attacher/OpenJ9VirtualMachine.java +++ b/jcl/src/jdk.attach/share/classes/com/ibm/tools/attach/attacher/OpenJ9VirtualMachine.java @@ -349,7 +349,8 @@ private void lockAllAttachNotificationSyncFiles( IPC.logMessage("lockAllAttachNotificationSyncFiles locking targetLocks[", vmdIndex, "] ", attachSyncFile); //$NON-NLS-1$ //$NON-NLS-2$ targetLocks[vmdIndex] = new FileLock(attachSyncFile, TargetDirectory.SYNC_FILE_PERMISSIONS); try { - targetLocks[vmdIndex].lockFile(true, "OpenJ9VirtualMachine.lockAllAttachNotificationSyncFiles"); //$NON-NLS-1$ + /* use FileLockWatchdogTask for non-CommonControlFile */ + targetLocks[vmdIndex].lockFile(true, "OpenJ9VirtualMachine.lockAllAttachNotificationSyncFiles", true); //$NON-NLS-1$ } catch (IOException e) { targetLocks[vmdIndex] = null; IPC.logMessage("lockAllAttachNotificationSyncFiles locking targetLocks[", vmdIndex, "] ", "already locked"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ diff --git a/test/functional/Java8andUp/src/org/openj9/test/fileLock/NativeFileLock.java b/test/functional/Java8andUp/src/org/openj9/test/fileLock/NativeFileLock.java index dd32fe56b49..13c93eba746 100644 --- a/test/functional/Java8andUp/src/org/openj9/test/fileLock/NativeFileLock.java +++ b/test/functional/Java8andUp/src/org/openj9/test/fileLock/NativeFileLock.java @@ -42,7 +42,7 @@ public NativeFileLock(File lockFile, int mode) throws Exception { nflConstructor.setAccessible(true); fileLockObject = nflConstructor.newInstance(lockFile.getAbsolutePath(), Integer.valueOf(mode)); lockFileMethod = nativeFileLock.getDeclaredMethod("lockFile", - boolean.class, String.class); + boolean.class, String.class, boolean.class); lockFileMethod.setAccessible(true); unlockFileMethod = nativeFileLock.getDeclaredMethod("unlockFile", String.class); unlockFileMethod.setAccessible(true); @@ -53,7 +53,8 @@ public NativeFileLock(File lockFile, int mode) throws Exception { public boolean lockFile(boolean blocking) throws Exception { Boolean result = Boolean.valueOf(true); TestFileLocking.logger.debug("lockfile blocking =" + blocking); - result = (Boolean) lockFileMethod.invoke(fileLockObject, Boolean.valueOf(blocking), "NativeFileLock.lockFile()"); + // The test has no different user involved, always locks file with FileLockWatchdogTask. + result = (Boolean) lockFileMethod.invoke(fileLockObject, Boolean.valueOf(blocking), "NativeFileLock.lockFile()", true); return result.booleanValue(); }