Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Do something about the new flood of pylint errors I caused #148

Closed
wants to merge 9 commits into from
31 changes: 13 additions & 18 deletions anaconda
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@

coverage = None

proc_cmdline = open("/proc/cmdline", "r").read()
# If we get a signal immediately after starting that would be pretty messed up
proc_cmdline = open("/proc/cmdline", "r").read() # pylint: disable=interruptible-system-call
proc_cmdline = proc_cmdline.split()
if ("debug=1" in proc_cmdline) or ("debug" in proc_cmdline):
import coverage
Expand All @@ -44,7 +45,7 @@ if ("debug=1" in proc_cmdline) or ("debug" in proc_cmdline):
cov.start()


import atexit, sys, os, time, signal, stat, errno
import atexit, sys, os, time, signal, stat

def exitHandler(rebootData, storage):
# Clear the list of watched PIDs.
Expand Down Expand Up @@ -119,14 +120,13 @@ def startSpiceVDAgent():
log.info("Started spice-vdagent.")

def startX11():
# Ignore stdout/stderr, since everything is logged to /tmp/X.log anyway
xfd = open("/dev/null", "wb")
import subprocess

# Start Xorg and wait for it become ready
iutil.startX(["Xorg", "-br", "-logfile", "/tmp/X.log",
":%s" % constants.X_DISPLAY_NUMBER, "vt6", "-s", "1440", "-ac",
"-nolisten", "tcp", "-dpi", "96",
"-noreset"], output_redirect=xfd)
"-noreset"], output_redirect=subprocess.DEVNULL)

# function to handle X startup special issues for anaconda
def doStartupX11Actions():
Expand Down Expand Up @@ -863,6 +863,7 @@ if __name__ == "__main__":
from pyanaconda import ntp
from pyanaconda import keyboard
from pyanaconda.iutil import ProxyString, ProxyStringError
from pyanaconda.iutil import open # pylint: disable=redefined-builtin

verdesc = "%s for %s %s" % (getAnacondaVersionString(),
product.productName, product.productVersion)
Expand Down Expand Up @@ -929,13 +930,12 @@ if __name__ == "__main__":
try:
with open(pidfile_path, 'r') as pidfile:
pid = int(pidfile.read())
except IOError as e:
except FileNotFoundError:
# Ignore errors due to the file not existing. Other errors mean (most
# likely) that we're not running as root, there's a filesystem error,
# or someone filled our PID file with garbage, so just let those be
# raised.
if e.errno != errno.ENOENT:
raise
pass
else:
# Is the PID still running?
if not os.path.isdir("/proc/%s" % pid):
Expand All @@ -952,14 +952,14 @@ if __name__ == "__main__":
os.unlink(pidfile_path)
# If it is anaconda, let the pidfile creation below fail
# and print an error
except IOError as e:
except (FileNotFoundError, ProcessLookupError):
# Ignore failures due to the file not existing in case the
# process ended while we were trying to read about it. Assume
# in this case that the process was another anaconda instance,
# and the PID file was cleaned up.
# If the process ended between open and read, we'll get ESRCH
if e.errno not in (errno.ENOENT, errno.ESRCH):
raise
# (ProcessLookupError)
pass

# Attempt to create the pidfile
try:
Expand All @@ -969,13 +969,8 @@ if __name__ == "__main__":
pidfile_created = True
pid_string = "%s\n" % os.getpid()
iutil.eintr_retry_call(os.write, pidfile, pid_string.encode("utf-8"))
iutil.eintr_retry_call(os.close, pidfile)
except OSError as e:
# If the failure was anything other than EEXIST during the open call,
# just re-raise the exception
if e.errno != errno.EEXIST:
raise

os.close(pidfile)
except FileExistsError:
log.error("%s already exists, exiting", pidfile_path)

# If we had a $DISPLAY at start and zenity is available, we may be
Expand Down
3 changes: 3 additions & 0 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
# All configuration values have a default; values that are commented out
# serve to show the default.

# Ignore any interruptible calls
# pylint: disable=interruptible-system-call

import sys, os

# If extensions (or modules to document with autodoc) are in another directory,
Expand Down
26 changes: 17 additions & 9 deletions dracut/driver-updates
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,15 @@ import readline # pylint:disable=unused-import

log = logging.getLogger("DD")

import functools
def eintr_retry_call(func, *args, **kwargs):
"""Retry an interruptible system call if interrupted."""
while True:
try:
return func(*args, **kwargs)
except InterruptedError:
continue
open = functools.partial(eintr_retry_call, open) # pylint: disable=redefined-builtin

class RunCmdError(Exception):
""" Raised when run_cmd gets a non-zero returncode
Expand All @@ -64,15 +73,14 @@ def run_cmd(cmd):
:raises: OSError if the cmd doesn't exist, RunCmdError if the rc != 0
"""
try:
with open("/dev/null", "w") as fd_null:
log.debug(" ".join(cmd))
proc = subprocess.Popen(cmd, universal_newlines=True,
stdout=subprocess.PIPE,
stderr=fd_null)
out = proc.communicate()[0]
if out:
for line in out.splitlines():
log.debug(line)
log.debug(" ".join(cmd))
proc = subprocess.Popen(cmd, universal_newlines=True,
stdout=subprocess.PIPE,
stderr=subprocess.DEVNULL)
out = proc.communicate()[0]
if out:
for line in out.splitlines():
log.debug(line)
except OSError as e:
log.error("Error running %s: %s", cmd[0], e.strerror)
raise
Expand Down
10 changes: 10 additions & 0 deletions dracut/parse-kickstart
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,16 @@ log = logging.getLogger('parse-kickstart').addHandler(logging.NullHandler())

TMPDIR = "/tmp"

import functools
def eintr_retry_call(func, *args, **kwargs):
"""Retry an interruptible system call if interrupted."""
while True:
try:
return func(*args, **kwargs)
except InterruptedError:
continue
open = functools.partial(eintr_retry_call, open) # pylint: disable=redefined-builtin

# Helper function for reading simple files in /sys
def readsysfile(f):
'''Return the contents of f, or "" if missing.'''
Expand Down
3 changes: 2 additions & 1 deletion pyanaconda/anaconda.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
from pyanaconda.bootloader import get_bootloader
from pyanaconda import constants
from pyanaconda import iutil
from pyanaconda.iutil import open # pylint: disable=redefined-builtin
from pyanaconda import addons

import logging
Expand Down Expand Up @@ -202,7 +203,7 @@ def dumpState(self):
dump_text += threads
dump_text = dump_text.encode("utf-8")
iutil.eintr_retry_call(os.write, fd, dump_text)
iutil.eintr_retry_call(os.close, fd)
os.close(fd)

# append to a given file
with open("/tmp/anaconda-tb-all.log", "a+") as f:
Expand Down
1 change: 1 addition & 0 deletions pyanaconda/anaconda_argparse.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
from argparse import ArgumentParser, ArgumentError, HelpFormatter, Namespace

from pyanaconda.flags import BootArgs
from pyanaconda.iutil import open # pylint: disable=redefined-builtin

import logging
log = logging.getLogger("anaconda")
Expand Down
6 changes: 6 additions & 0 deletions pyanaconda/anaconda_log.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,9 @@ def updateRemote(self, remote_syslog):

Requires updating rsyslogd config and restarting rsyslog
"""
# Import here instead of at the module level to avoid an import loop
from pyanaconda.iutil import open # pylint: disable=redefined-builtin

TEMPLATE = "*.* @@%s\n"

self.remote_syslog = remote_syslog
Expand All @@ -233,6 +236,9 @@ def updateRemote(self, remote_syslog):
def setupVirtio(self):
"""Setup virtio rsyslog logging.
"""
# Import here instead of at the module level to avoid an import loop
from pyanaconda.iutil import open # pylint: disable=redefined-builtin

TEMPLATE = "*.* %s;anaconda_syslog\n"

vport = flags.cmdline.get('virtiolog') or self.VIRTIO_PORT
Expand Down
11 changes: 6 additions & 5 deletions pyanaconda/bootloader.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
from itertools import chain

from pyanaconda import iutil
from pyanaconda.iutil import open # pylint: disable=redefined-builtin
from blivet.devicelibs import raid
from pyanaconda.isys import sync
from pyanaconda.product import productName
Expand Down Expand Up @@ -61,7 +62,7 @@ def get_boot_block(device, seek_blocks=0):
if seek_blocks:
os.lseek(fd, seek_blocks * block_size, 0)
block = iutil.eintr_retry_call(os.read, fd, 512)
iutil.eintr_retry_call(os.close, fd)
os.close(fd)
if not status:
try:
device.teardown(recursive=True)
Expand Down Expand Up @@ -1347,11 +1348,11 @@ def install(self, args=None):
"stage2dev": self.grub_device_name(stage2dev)})
(pread, pwrite) = os.pipe()
iutil.eintr_retry_call(os.write, pwrite, cmd.encode("utf-8"))
iutil.eintr_retry_call(os.close, pwrite)
os.close(pwrite)
args = ["--batch", "--no-floppy",
"--device-map=%s" % self.device_map_file]
rc = iutil.execInSysroot("grub", args, stdin=pread)
iutil.eintr_retry_call(os.close, pread)
os.close(pread)
if rc:
raise BootLoaderError("boot loader install failed")

Expand Down Expand Up @@ -1540,11 +1541,11 @@ def _encrypt_password(self):
(pread, pwrite) = os.pipe()
passwords = "%s\n%s\n" % (self.password, self.password)
iutil.eintr_retry_call(os.write, pwrite, passwords.encode("utf-8"))
iutil.eintr_retry_call(os.close, pwrite)
os.close(pwrite)
buf = iutil.execWithCapture("grub2-mkpasswd-pbkdf2", [],
stdin=pread,
root=iutil.getSysroot())
iutil.eintr_retry_call(os.close, pread)
os.close(pread)
self.encrypted_password = buf.split()[-1].strip()
if not self.encrypted_password.startswith("grub.pbkdf2."):
raise BootLoaderError("failed to encrypt boot loader password")
Expand Down
1 change: 1 addition & 0 deletions pyanaconda/desktop.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import os
from pyanaconda.constants import RUNLEVELS
from pyanaconda import iutil
from pyanaconda.iutil import open # pylint: disable=redefined-builtin

import logging
log = logging.getLogger("anaconda")
Expand Down
10 changes: 5 additions & 5 deletions pyanaconda/exception.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,11 +196,11 @@ def runDebug(self, exc_info):
iutil.vtActivate(1)

iutil.eintr_retry_call(os.open, "/dev/console", os.O_RDWR) # reclaim stdin
iutil.eintr_retry_call(os.dup2, 0, 1) # reclaim stdout
iutil.eintr_retry_call(os.dup2, 0, 2) # reclaim stderr
# ^
# |
# +------ dup2 is magic, I tells ya!
os.dup2(0, 1) # reclaim stdout
os.dup2(0, 2) # reclaim stderr
# ^
# |
# +------ dup2 is magic, I tells ya!

# bring back the echo
import termios
Expand Down
4 changes: 4 additions & 0 deletions pyanaconda/flags.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,10 @@ def read(self, filenames):
Returns a list of successfully read files.
filenames can contain *, ?, and character ranges expressed with []
"""

# Import here instead of at the module level to avoid an import loop
from pyanaconda.iutil import open # pylint: disable=redefined-builtin

readfiles = []
if isinstance(filenames, str):
filenames = [filenames]
Expand Down
1 change: 1 addition & 0 deletions pyanaconda/image.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
from pyanaconda import isys
import os, os.path, stat, tempfile
from pyanaconda.constants import ISO_DIR
from pyanaconda.iutil import open # pylint: disable=redefined-builtin

from pyanaconda.errors import errorHandler, ERROR_RAISE, InvalidImageSizeError, MediaMountError, MissingImageError

Expand Down
1 change: 1 addition & 0 deletions pyanaconda/install.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
from pyanaconda.users import createLuserConf, getPassAlgo, Users
from pyanaconda import flags
from pyanaconda import iutil
from pyanaconda.iutil import open # pylint: disable=redefined-builtin
from pyanaconda import timezone
from pyanaconda import network
from pyanaconda.i18n import _
Expand Down
1 change: 1 addition & 0 deletions pyanaconda/isys/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import time
import datetime
import pytz
from pyanaconda.iutil import open # pylint: disable=redefined-builtin

import logging
log = logging.getLogger("anaconda")
Expand Down
28 changes: 18 additions & 10 deletions pyanaconda/iutil.py
Original file line number Diff line number Diff line change
Expand Up @@ -509,9 +509,8 @@ def _sigchld_handler(num=None, frame=None):
for child_pid in _forever_pids:
try:
pid_result, status = eintr_retry_call(os.waitpid, child_pid, os.WNOHANG)
except OSError as e:
if e.errno == errno.ECHILD:
continue
except ChildProcessError:
continue

if pid_result:
proc_name = _forever_pids[child_pid][0]
Expand Down Expand Up @@ -1288,22 +1287,20 @@ def ipmi_report(event):
# Event data 2 & 3 - always 0x0 for us
event_string = "0x4 0x1F 0x0 0x6f %#x 0x0 0x0\n" % event
eintr_retry_call(os.write, fd, event_string.encode("utf-8"))
eintr_retry_call(os.close, fd)
os.close(fd)

execWithCapture("ipmitool", ["sel", "add", path])

os.remove(path)

# Copied from python's subprocess.py
def eintr_retry_call(func, *args):
def eintr_retry_call(func, *args, **kwargs):
"""Retry an interruptible system call if interrupted."""
while True:
try:
return func(*args)
except (OSError, IOError) as e:
if e.errno == errno.EINTR:
continue
raise
return func(*args, **kwargs)
except InterruptedError:
continue

def parent_dir(directory):
"""Return the parent's path"""
Expand All @@ -1315,3 +1312,14 @@ def requests_session():
session.mount("file://", FileAdapter())
session.mount("ftp://", FTPAdapter())
return session

_open = open
def open(*args, **kwargs): # pylint: disable=redefined-builtin
"""Open a file, and retry on EINTR.

The arguments are the same as those to python's builtin open.

This is equivalent to eintr_retry_call(open, ...). Some other
high-level languages handle this for you, like C's fopen.
"""
return eintr_retry_call(_open, *args, **kwargs)
1 change: 1 addition & 0 deletions pyanaconda/keyboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
from pyanaconda import safe_dbus
from pyanaconda.constants import DEFAULT_VC_FONT, DEFAULT_KEYBOARD
from pyanaconda.flags import can_touch_runtime_system
from pyanaconda.iutil import open # pylint: disable=redefined-builtin

from gi.repository import GLib

Expand Down
3 changes: 2 additions & 1 deletion pyanaconda/kickstart.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@

import glob
from pyanaconda import iutil
from pyanaconda.iutil import open # pylint: disable=redefined-builtin
import os
import os.path
import tempfile
Expand Down Expand Up @@ -104,7 +105,7 @@ def run(self, chroot):
(fd, path) = tempfile.mkstemp("", "ks-script-", scriptRoot + "/tmp")

iutil.eintr_retry_call(os.write, fd, self.script.encode("utf-8"))
iutil.eintr_retry_call(os.close, fd)
os.close(fd)
iutil.eintr_retry_call(os.chmod, path, 0o700)

# Always log stdout/stderr from scripts. Using --log just lets you
Expand Down
1 change: 1 addition & 0 deletions pyanaconda/localization.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@

from pyanaconda import constants
from pyanaconda.iutil import upcase_first_letter, setenv
from pyanaconda.iutil import open # pylint: disable=redefined-builtin

import logging
log = logging.getLogger("anaconda")
Expand Down