Revision 7d88772a

b/daemons/ganeti-masterd
429 429
  utils.debug = options.debug
430 430
  utils.no_fork = True
431 431

  
432
  if options.fork:
433
    utils.CloseFDs()
434

  
432 435
  rpc.Init()
433 436
  try:
434 437
    ssconf.CheckMaster(options.debug)
......
460 463

  
461 464
  # become a daemon
462 465
  if options.fork:
463
    utils.Daemonize(logfile=constants.LOG_MASTERDAEMON,
464
                    noclose_fds=[master.fileno()])
466
    utils.Daemonize(logfile=constants.LOG_MASTERDAEMON)
465 467

  
466 468
  utils.WritePidFile(constants.MASTERD_PID)
467 469
  try:
b/daemons/ganeti-noded
704 704

  
705 705
  options, args = ParseOptions()
706 706
  utils.debug = options.debug
707

  
708
  if options.fork:
709
    utils.CloseFDs()
710

  
707 711
  for fname in (constants.SSL_CERT_FILE,):
708 712
    if not os.path.isfile(fname):
709 713
      print "config %s not there, will not run." % fname
b/daemons/ganeti-rapi
191 191
  """
192 192
  options, args = ParseOptions()
193 193

  
194
  if options.fork:
195
    utils.CloseFDs()
196

  
194 197
  ssconf.CheckMaster(options.debug)
195 198

  
196 199
  if options.fork:
b/lib/utils.py
1348 1348
  return True
1349 1349

  
1350 1350

  
1351
def Daemonize(logfile, noclose_fds=None):
1352
  """Daemonize the current process.
1351
def _CloseFDNoErr(fd, retries=5):
1352
  """Close a file descriptor ignoring errors.
1353 1353

  
1354
  This detaches the current process from the controlling terminal and
1355
  runs it in the background as a daemon.
1354
  @type fd: int
1355
  @param fd: the file descriptor
1356
  @type retries: int
1357
  @param retries: how many retries to make, in case we get any
1358
      other error than EBADF
1359

  
1360
  """
1361
  try:
1362
    os.close(fd)
1363
  except OSError, err:
1364
    if err.errno != errno.EBADF:
1365
      if retries > 0:
1366
        _CloseFDNoErr(fd, retries - 1)
1367
    # else either it's closed already or we're out of retries, so we
1368
    # ignore this and go on
1369

  
1370

  
1371
def CloseFDs(noclose_fds=None):
1372
  """Close file descriptors.
1373

  
1374
  This closes all file descriptors above 2 (i.e. except
1375
  stdin/out/err).
1356 1376

  
1357
  @type logfile: str
1358
  @param logfile: the logfile to which we should redirect stdout/stderr
1359 1377
  @type noclose_fds: list or None
1360 1378
  @param noclose_fds: if given, it denotes a list of file descriptor
1361 1379
      that should not be closed
1362
  @rtype: int
1363
  @returns: the value zero
1364 1380

  
1365 1381
  """
1366
  UMASK = 077
1367
  WORKDIR = "/"
1368 1382
  # Default maximum for the number of available file descriptors.
1369 1383
  if 'SC_OPEN_MAX' in os.sysconf_names:
1370 1384
    try:
......
1375 1389
      MAXFD = 1024
1376 1390
  else:
1377 1391
    MAXFD = 1024
1392
  maxfd = resource.getrlimit(resource.RLIMIT_NOFILE)[1]
1393
  if (maxfd == resource.RLIM_INFINITY):
1394
    maxfd = MAXFD
1395

  
1396
  # Iterate through and close all file descriptors (except the standard ones)
1397
  for fd in range(3, maxfd):
1398
    if noclose_fds and fd in noclose_fds:
1399
      continue
1400
    _CloseFDNoErr(fd)
1401

  
1402

  
1403
def Daemonize(logfile):
1404
  """Daemonize the current process.
1405

  
1406
  This detaches the current process from the controlling terminal and
1407
  runs it in the background as a daemon.
1408

  
1409
  @type logfile: str
1410
  @param logfile: the logfile to which we should redirect stdout/stderr
1411
  @rtype: int
1412
  @returns: the value zero
1413

  
1414
  """
1415
  UMASK = 077
1416
  WORKDIR = "/"
1378 1417

  
1379 1418
  # this might fail
1380 1419
  pid = os.fork()
......
1390 1429
      os._exit(0) # Exit parent (the first child) of the second child.
1391 1430
  else:
1392 1431
    os._exit(0) # Exit parent of the first child.
1393
  maxfd = resource.getrlimit(resource.RLIMIT_NOFILE)[1]
1394
  if (maxfd == resource.RLIM_INFINITY):
1395
    maxfd = MAXFD
1396 1432

  
1397
  # Iterate through and close all file descriptors.
1398
  for fd in range(0, maxfd):
1399
    if noclose_fds and fd in noclose_fds:
1400
      continue
1401
    try:
1402
      os.close(fd)
1403
    except OSError: # ERROR, fd wasn't open to begin with (ignored)
1404
      pass
1405
  os.open(logfile, os.O_RDWR|os.O_CREAT|os.O_APPEND, 0600)
1406
  # Duplicate standard input to standard output and standard error.
1407
  os.dup2(0, 1)     # standard output (1)
1408
  os.dup2(0, 2)     # standard error (2)
1433
  for fd in range(3):
1434
    _CloseFDNoErr(fd)
1435
  i = os.open("/dev/null", os.O_RDONLY) # stdin
1436
  assert i == 0, "Can't close/reopen stdin"
1437
  i = os.open(logfile, os.O_WRONLY|os.O_CREAT|os.O_APPEND, 0600) # stdout
1438
  assert i == 1, "Can't close/reopen stdout"
1439
  # Duplicate standard output to standard error.
1440
  os.dup2(1, 2)
1409 1441
  return 0
1410 1442

  
1411 1443

  
......
1649 1681

  
1650 1682
  # Remove all previously setup handlers
1651 1683
  for handler in root_logger.handlers:
1684
    handler.close()
1652 1685
    root_logger.removeHandler(handler)
1653 1686

  
1654 1687
  if stderr_logging:

Also available in: Unified diff