This is an automated email from the ASF dual-hosted git repository.

bejancsaba pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/nifi.git


The following commit(s) were added to refs/heads/main by this push:
     new 3c3cf9976e NIFI-11761 Fixed MiNiFi restart issue when graceful 
shutdown period expires. MiNiFi restart sends bootstrap to background
3c3cf9976e is described below

commit 3c3cf9976ec18a9b67dc5a435a01e4d48be12151
Author: Ferenc Kis <[email protected]>
AuthorDate: Wed Jun 28 16:24:00 2023 +0200

    NIFI-11761 Fixed MiNiFi restart issue when graceful shutdown period 
expires. MiNiFi restart sends bootstrap to background
    
    Signed-off-by: Csaba Bejan <[email protected]>
    
    This closes #7448.
---
 .../apache/nifi/minifi/bootstrap/RunMiNiFi.java    |  9 +++++--
 .../nifi/minifi/bootstrap/command/StopRunner.java  |  4 ++-
 .../minifi/bootstrap/util/UnixProcessUtils.java    | 30 ++++++++++++++++++----
 .../src/main/resources/bin/minifi.sh               |  8 +++---
 4 files changed, 39 insertions(+), 12 deletions(-)

diff --git 
a/minifi/minifi-bootstrap/src/main/java/org/apache/nifi/minifi/bootstrap/RunMiNiFi.java
 
b/minifi/minifi-bootstrap/src/main/java/org/apache/nifi/minifi/bootstrap/RunMiNiFi.java
index 1c141547a0..dac7febab6 100644
--- 
a/minifi/minifi-bootstrap/src/main/java/org/apache/nifi/minifi/bootstrap/RunMiNiFi.java
+++ 
b/minifi/minifi-bootstrap/src/main/java/org/apache/nifi/minifi/bootstrap/RunMiNiFi.java
@@ -14,6 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package org.apache.nifi.minifi.bootstrap;
 
 import static java.util.Collections.singleton;
@@ -76,6 +77,8 @@ public class RunMiNiFi implements ConfigurationFileHolder {
     private static final String STATUS_FILE_PORT_KEY = "port";
     private static final String STATUS_FILE_SECRET_KEY = "secret.key";
     private static final String ACKNOWLEDGE_OPERATION = 
"ACKNOWLEDGE_OPERATION";
+    private static final String PROCESS_KILL_SUCCESS_CHECK_RETRIES_KEY = 
"process.kill.success.check.retries";
+    private static final String PROCESS_KILL_SUCCESS_CHECK_RETRIES_DEFAULT = 
"30";
 
     private final BootstrapFileProvider bootstrapFileProvider;
     private final ConfigurationChangeCoordinator 
configurationChangeCoordinator;
@@ -98,18 +101,20 @@ public class RunMiNiFi implements ConfigurationFileHolder {
         bootstrapFileProvider = new BootstrapFileProvider(bootstrapConfigFile);
         objectMapper = getObjectMapper();
         Properties properties = bootstrapFileProvider.getStatusProperties();
+        Properties bootstrapProperties = 
bootstrapFileProvider.getBootstrapProperties();
 
         miNiFiParameters = new MiNiFiParameters(
             
Optional.ofNullable(properties.getProperty(STATUS_FILE_PORT_KEY)).map(Integer::parseInt).orElse(UNINITIALIZED),
             
Optional.ofNullable(properties.getProperty(STATUS_FILE_PID_KEY)).map(Integer::parseInt).orElse(UNINITIALIZED),
             properties.getProperty(STATUS_FILE_SECRET_KEY)
         );
-        ProcessUtils processUtils = new UnixProcessUtils();
+        ProcessUtils processUtils = new UnixProcessUtils(Integer.parseInt(
+            
bootstrapProperties.getProperty(PROCESS_KILL_SUCCESS_CHECK_RETRIES_KEY, 
PROCESS_KILL_SUCCESS_CHECK_RETRIES_DEFAULT)));
 
         miNiFiCommandSender = new MiNiFiCommandSender(miNiFiParameters, 
objectMapper);
         MiNiFiStatusProvider miNiFiStatusProvider = new 
MiNiFiStatusProvider(miNiFiCommandSender, processUtils);
         periodicStatusReporterManager =
-            new 
PeriodicStatusReporterManager(bootstrapFileProvider.getBootstrapProperties(), 
miNiFiStatusProvider, miNiFiCommandSender, miNiFiParameters);
+            new PeriodicStatusReporterManager(bootstrapProperties, 
miNiFiStatusProvider, miNiFiCommandSender, miNiFiParameters);
         MiNiFiConfigurationChangeListener configurationChangeListener = new 
MiNiFiConfigurationChangeListener(this, DEFAULT_LOGGER, bootstrapFileProvider);
         configurationChangeCoordinator = new 
ConfigurationChangeCoordinator(bootstrapFileProvider, this, 
singleton(configurationChangeListener));
 
diff --git 
a/minifi/minifi-bootstrap/src/main/java/org/apache/nifi/minifi/bootstrap/command/StopRunner.java
 
b/minifi/minifi-bootstrap/src/main/java/org/apache/nifi/minifi/bootstrap/command/StopRunner.java
index db980d5c52..a5f3413e94 100644
--- 
a/minifi/minifi-bootstrap/src/main/java/org/apache/nifi/minifi/bootstrap/command/StopRunner.java
+++ 
b/minifi/minifi-bootstrap/src/main/java/org/apache/nifi/minifi/bootstrap/command/StopRunner.java
@@ -45,7 +45,7 @@ public class StopRunner implements CommandRunner {
     private final ProcessUtils processUtils;
 
     public StopRunner(BootstrapFileProvider bootstrapFileProvider, 
MiNiFiParameters miNiFiParameters, MiNiFiCommandSender miNiFiCommandSender,
-        CurrentPortProvider currentPortProvider, 
GracefulShutdownParameterProvider gracefulShutdownParameterProvider, 
ProcessUtils processUtils) {
+                      CurrentPortProvider currentPortProvider, 
GracefulShutdownParameterProvider gracefulShutdownParameterProvider, 
ProcessUtils processUtils) {
         this.bootstrapFileProvider = bootstrapFileProvider;
         this.miNiFiParameters = miNiFiParameters;
         this.miNiFiCommandSender = miNiFiCommandSender;
@@ -56,6 +56,7 @@ public class StopRunner implements CommandRunner {
 
     /**
      * Shutdown the MiNiFi and the managing bootstrap process as well.
+     *
      * @param args the input arguments
      * @return status code
      */
@@ -94,6 +95,7 @@ public class StopRunner implements CommandRunner {
                 status = ERROR.getStatusCode();
             }
         } catch (IOException e) {
+            CMD_LOGGER.warn("An error has occurred while stopping MiNiFi. 
Force killing process with pid=" + minifiPid, e);
             killProcessTree(minifiPid);
         } finally {
             if (lockFile.exists() && !lockFile.delete()) {
diff --git 
a/minifi/minifi-bootstrap/src/main/java/org/apache/nifi/minifi/bootstrap/util/UnixProcessUtils.java
 
b/minifi/minifi-bootstrap/src/main/java/org/apache/nifi/minifi/bootstrap/util/UnixProcessUtils.java
index 1a13138696..8a1a8ee65c 100644
--- 
a/minifi/minifi-bootstrap/src/main/java/org/apache/nifi/minifi/bootstrap/util/UnixProcessUtils.java
+++ 
b/minifi/minifi-bootstrap/src/main/java/org/apache/nifi/minifi/bootstrap/util/UnixProcessUtils.java
@@ -37,6 +37,12 @@ import org.slf4j.LoggerFactory;
 public class UnixProcessUtils implements ProcessUtils {
     private static final Logger LOGGER = 
LoggerFactory.getLogger(UnixProcessUtils.class);
 
+    private final int processKillCheckRetries;
+
+    public UnixProcessUtils(int processKillCheckRetries) {
+        this.processKillCheckRetries = processKillCheckRetries;
+    }
+
     @Override
     public boolean isProcessRunning(Long pid) {
         if (pid == null) {
@@ -55,8 +61,8 @@ public class UnixProcessUtils implements ProcessUtils {
             boolean running = false;
             String line;
             try (InputStream in = proc.getInputStream();
-                Reader streamReader = new InputStreamReader(in);
-                BufferedReader reader = new BufferedReader(streamReader)) {
+                 Reader streamReader = new InputStreamReader(in);
+                 BufferedReader reader = new BufferedReader(streamReader)) {
 
                 while ((line = reader.readLine()) != null) {
                     if (line.trim().startsWith(pidString)) {
@@ -113,14 +119,28 @@ public class UnixProcessUtils implements ProcessUtils {
             killProcessTree(childPid);
         }
 
-        Runtime.getRuntime().exec(new String[]{"kill", "-9", 
String.valueOf(pid)});
+        Runtime.getRuntime().exec(new String[] {"kill", "-9", 
String.valueOf(pid)});
+
+        int retries = processKillCheckRetries;
+        while (isProcessRunning(pid)) {
+            if (retries == 0) {
+                throw new IOException("Failed to stop process. Process is 
still running after killing attempt with pid=" + pid);
+            }
+            LOGGER.warn("Process is still running after killing attempt with 
pid=" + pid);
+            retries--;
+            try {
+                Thread.sleep(1000);
+            } catch (InterruptedException e) {
+                DEFAULT_LOGGER.warn("Thread interrupted while waiting for 
killing process with pid=" + pid);
+            }
+        }
     }
 
     private List<Long> getChildProcesses(Long ppid) throws IOException {
-        Process proc = Runtime.getRuntime().exec(new String[]{"ps", "-o", 
"pid", "--no-headers", "--ppid", String.valueOf(ppid)});
+        Process proc = Runtime.getRuntime().exec(new String[] {"ps", "-o", 
"pid", "--no-headers", "--ppid", String.valueOf(ppid)});
         List<Long> childPids = new ArrayList<>();
         try (InputStream in = proc.getInputStream();
-            BufferedReader reader = new BufferedReader(new 
InputStreamReader(in))) {
+             BufferedReader reader = new BufferedReader(new 
InputStreamReader(in))) {
 
             String line;
             while ((line = reader.readLine()) != null) {
diff --git 
a/minifi/minifi-nar-bundles/minifi-framework-bundle/minifi-framework/minifi-resources/src/main/resources/bin/minifi.sh
 
b/minifi/minifi-nar-bundles/minifi-framework-bundle/minifi-framework/minifi-resources/src/main/resources/bin/minifi.sh
index 5c33b7b2ff..c5c0004bd3 100755
--- 
a/minifi/minifi-nar-bundles/minifi-framework-bundle/minifi-framework/minifi-resources/src/main/resources/bin/minifi.sh
+++ 
b/minifi/minifi-nar-bundles/minifi-framework-bundle/minifi-framework/minifi-resources/src/main/resources/bin/minifi.sh
@@ -326,23 +326,23 @@ run() {
     fi
 
     if [ "$1" = "run" ]; then
-      # Use exec to handover PID to RunMiNiFi java process, instead of foking 
it as a child process
+      # Use exec to handover PID to RunMiNiFi java process, instead of forking 
it as a child process
       RUN_MINIFI_CMD="exec ${RUN_MINIFI_CMD}"
     fi
 
     # run 'start' in the background because the process will continue to run, 
monitoring MiNiFi.
     # all other commands will terminate quickly so want to just wait for them
-    if [ "$1" = "start" ]; then
+    if [ "$1" = "start" ] || [ "$1" = "restart" ]; then
         (eval "cd ${MINIFI_HOME} && ${RUN_MINIFI_CMD}" &)
     else
         eval "cd ${MINIFI_HOME} && ${RUN_MINIFI_CMD}"
     fi
     EXIT_STATUS=$?
 
-    # Wait just a bit (3 secs) to wait for the logging to finish and then echo 
a new-line.
+    # Wait just a bit (5 secs) to wait for the logging to finish and then echo 
a new-line.
     # We do this to avoid having logs spewed on the console after running the 
command and then not giving
     # control back to the user
-    sleep 3
+    sleep 5
     echo
 }
 

Reply via email to