Logo Search packages:      
Sourcecode: condor version File versions  Download package

limit.cpp

/***************************************************************
 *
 * Copyright (C) 1990-2007, Condor Team, Computer Sciences Department,
 * University of Wisconsin-Madison, WI.
 * 
 * Licensed 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.
 *
 ***************************************************************/


#include "condor_common.h"
#include "condor_debug.h"
#include "condor_syscall_mode.h"
#include "limit.h"

extern "C" {

void
limit( int resource, rlim_t new_limit, int kind )
{
      int         scm;
      struct      rlimit current = {0,0};
      struct      rlimit desired = {0,0};

      scm = SetSyscalls( SYS_LOCAL | SYS_RECORDED );

      /* Find out current limit for this resource */
      if( getrlimit(resource, &current) < 0 ) {
            EXCEPT( "getrlimit(%d): errno: %d(%s)", 
                              resource, errno, strerror(errno));
      }

      switch(kind) {
            case CONDOR_SOFT_LIMIT:
                  /* Make a new rlimit structure that holds what I desire to be 
                        true */
                  desired.rlim_cur = new_limit;
                  desired.rlim_max = current.rlim_max;

                  /* Don't try to exceed the hard max as supplied by getrlimit() */
                  if( desired.rlim_cur > desired.rlim_max ) {
                        desired.rlim_cur = desired.rlim_max;
                  }

                  break;

            case CONDOR_HARD_LIMIT:
                  desired.rlim_cur = new_limit;
                  desired.rlim_max = new_limit;

                  if ((desired.rlim_max > current.rlim_max) && (getuid() != (pid_t)0))
                  {
                        /* Due to the fact that this code
                              path will happen a lot as a non
                              root user due to the the behavior
                              in Create_Process where we always
                              try to set the core hard limit to
                              the maximum of size_t by default,
                              we will by default ALWAYS ask
                              for a limit which may be larger
                              than the current hard max of
                              this limit. Especially in the
                              case of a personal Condor this
                              will result in whatever message
                              being written here being printed
                              out *all the time*. So, instead
                              of doing a dprintf for SNAFU
                              behavior, we silently truncate
                              the asked for limit the to
                              current hard max if it is greater.
                        */

                        desired = current;

                        desired.rlim_cur = desired.rlim_max;
                  }

                  break;

            default:
                  EXCEPT("do_limit() unknown limit enforcment policy. Programmer "
                        "Error.");
                  break;
      }

      /* Set the new limit */
      if( setrlimit(resource, &desired) < 0 ) {
            if (errno == EPERM ) {
            /* Under tru64, this setrlimit() fails oddly in that we
                  are following the API restrictions exactly(not
                  adjusting the maximum up as non-root, and not
                  asking for more soft limit than hard limit),
                  but still the kernel refuses to honor the
                  change we wish to make and responds with a
                  nonsensical EPERM failure. So we'll see if we
                  can do something reasonable before giving up
                  and not setting it at all. This code will be
                  kept common for all architectures in the hopes
                  that it will handle failures of this kind
                  everywhere. We're going to try and bound the
                  resource limit to UINT_MAX if we are able. */

            dprintf( D_ALWAYS, 
                  "Unexpected permissions failure in setting limits for resource "
                  "kind %d. setrlimit(%d, new = [rlim_cur = %lu, rlim_max = %lu]) : "
                  "old = [rlim_cur = %lu, rlim_max = %lu], errno: %d(%s). Attempting "
                  "workaround.\n",
                  resource, 
                  resource,
                  (unsigned long)desired.rlim_cur, 
                  (unsigned long)desired.rlim_max, 
                  (unsigned long)current.rlim_cur, 
                  (unsigned long)current.rlim_max,
                  errno, 
                  strerror(errno) );

                  /* bound the resource limit to UINT_MAX, if I can */
                  if (desired.rlim_cur > UINT_MAX && 
                        current.rlim_max >= UINT_MAX)
                  {
                        desired.rlim_cur = UINT_MAX;
                        if (setrlimit(resource, &desired) < 0) {
                              dprintf( D_ALWAYS, "Workaround failed with error %d(%s). "
                                    "Not adjusting limit for resource %d\n", 
                                    errno, strerror(errno), resource);

                        } else {
                              dprintf( D_ALWAYS, "Workaround enabled. Limit for "
                                    "resource %d is this: "
                                    "new = [rlim_cur = %lu, rlim_max = %lu]\n",
                                    resource, desired.rlim_cur, desired.rlim_max);
                        }
                  } else {
                        dprintf( D_ALWAYS, "Workaround not applicable, no limit "
                              "enforcement for resource %d.\n", resource);
                  }

            } else {
                  /* if this is something other than a permission problem
                        given the legal use of the setrlimit() interface */

                  EXCEPT( "Unexpected failure in setting limits for resource "
                  "kind %d. setrlimit(%d, new = [rlim_cur = %lu, rlim_max = %lu]) : "
                  "old = [rlim_cur = %lu, rlim_max = %lu], errno: %d(%s). \n",
                  resource, 
                  resource,
                  (unsigned long)desired.rlim_cur, 
                  (unsigned long)desired.rlim_max, 
                  (unsigned long)current.rlim_cur, 
                  (unsigned long)current.rlim_max,
                  errno, 
                  strerror(errno) );
            }
      }

      (void)SetSyscalls( scm );
}

} /* extern "C" */

Generated by  Doxygen 1.6.0   Back to index