Uploaded image for project: 'Jenkins'
  1. Jenkins
  2. JENKINS-53155

Gracefully restart jenkins

XMLWordPrintable

    • Icon: New Feature New Feature
    • Resolution: Unresolved
    • Icon: Minor Minor
    • core
    • jetty 9
      jenkins 2.138
      ubuntu

      Hi,

      from what I see, up to now, Jenkins can not gracefully exit, i.e. without killing the process it is  embedded within. 

      Steps to Reproduce:

      run multiple jenkins instances as webapps within a jetty installation/service.

      This results in multiple jenkins instances being started from one jetty process.

      Using the default lifecycle, i.e. the unixlifecylce, the entire jetty service is restarted upon calling Lifecycle.getLifecycle().restart(), which is what the unixlifecycle does.

      Desired Behavior:

      A way to restart only one of those Jenkins instances. For jetty a simple 

      touch /opt/jetty/webapps/jenkins_1.war
      // or
      touch /opt/jetty/webapps/jenkins_1.xml

      would, for example be sufficient to restart jenkins.

      What I have tried:

      I have tried creating a custom lifecycle to execute an arbitrary command. It looks like this (the entire plugin is attached):

      @Extension
      public class CustomRestartLifecycle extends Lifecycle {
          private static final Logger LOGGER = Logger.getLogger(CustomRestartLifecycle.class.getName());
      
          private String customCommand = "/usr/bin/touch /opt/jetty/webapps/mardyn.xml";
      
          public CustomRestartLifecycle() {
          }
      
          @Override
          public void restart() throws IOException, InterruptedException {
              Jenkins jenkins = Jenkins.getInstanceOrNull();  // guard against repeated concurrent calls to restart
      
              // first do cleanUp of Jenkins
              try {
                  if (jenkins != null) {
                      jenkins.cleanUp();
                  }
              } catch (Exception e) {
                  LOGGER.log(Level.SEVERE, "Failed to clean up. Restart will continue.", e);
              }
      
              // close all files upon exec, except stdin, stdout, and stderr
              // you will need an exec-family call afterwards!
              int sz = LIBC.getdtablesize();
              for(int i=3; i<sz; i++) {
                  int flags = LIBC.fcntl(i, F_GETFD);
                  if(flags<0) continue;
                  LIBC.fcntl(i, F_SETFD,flags| FD_CLOEXEC);
              }
      
              LOGGER.log(Level.INFO, "executing custom restart command: " + customCommand);
      
              // start new process with custom command
              String exe = customCommand.split(" ")[0];
              LIBC.execvp(exe, new StringArray(customCommand.split(" ")));
              throw new IOException("Failed to exec '"+exe+"' "+LIBC.strerror(Native.getLastError()));
              // Runtime.getRuntime().exec(customCommand.split(" "));
          }
      }
      

      Problem:

      Without closing the file handles, open file handles will remain and jenkins will not be able to update plugins properly. the jetty service will have to be restarted for that.

      Alternatively the calls from the UnixLifecycle (LIBC.fcntl(i, F_SETFD,flags| FD_CLOEXEC);) to close the file handles will crash the entire jetty instance. And it will have to be restarted.

       

      Possible Solutions:

      1. fix the closing of open file handles and only close those belonging to the own jenkins instance. 
      2. run only one jenkins instance in one process, thus requiring multiple jetty servers/instances

      I would actually prefer the first solution. Is there actually a way to do this?

       

       

       

            Unassigned Unassigned
            seckler Steffen Seckler
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated: