Giter VIP home page Giter VIP logo

Comments (12)

phillipberndt avatar phillipberndt commented on May 25, 2024 1

Your "environment stealing" is a very clever workaround by the way. It might even be worthwhile to
extract that to its own script

I'll leave it in place here, because I've made the promise that autorandr would always remain a contained, single-file script without dependencies. But feel free to extract it into its own tool anyway if you feel you'd find some use for it :-) (Might be an idea to use psutil to be cross-platform compatible in that case.)

from autorandr.

blueyed avatar blueyed commented on May 25, 2024

why does autorandr use an system wide service file instead of systemd-user?

Is it possible to have something for this by default per user then?

from autorandr.

timokau avatar timokau commented on May 25, 2024

I'm not sure what you mean. I'm talking about systemd user units.

from autorandr.

phillipberndt avatar phillipberndt commented on May 25, 2024

When autorandr gets triggered by udev, I get the following logs:

This seems to be correct. No need to worry about the first two errors, they mean that the instance run as root does not have access to the display. The last line is the important one: It states that the global (batch) instance of autorandr forks a new instance of autorandr, running as your user, and that copy will have XAUTHORITY set properly (if it didn't, you'd see another error message from that copy).

..or do you have reason to believe that autorandr doesn't work?

As an aside, why does autorandr use an system wide service file instead of systemd-user?

For two reasons, (1) I don't know whether user instances of systemd trigger sleep.target, (2) it's much easier to invoke a system service from udev than to invoke any existing user instance that might have a unit named autorandr.service.

from autorandr.

timokau avatar timokau commented on May 25, 2024

the global (batch) instance of autorandr forks a new instance of autorandr
Why does it just do this after first triggering the error?

..or do you have reason to believe that autorandr doesn't work?

Yes, it doesn't apply the profile after those logs are shown. If I manually run autorandr -c however, it does.

(1) I don't know whether user instances of systemd trigger sleep.target

I'm pretty sure systemd-user works with the same targets as the global systemd.

(2) it's much easier to invoke a system service from udev than to invoke any existing user instance that might have a unit named autorandr.service.

That's true. I did a little research how you could acomplish this, and I came up with a kind-of-but-not-quite working solution:

  • Having this autorandr.service file as a systemd-user service:
[Service]
Type=oneshot
ExecStart=/usr/bin/autorandr -c
  • Having this udev rule, using the horribly underdocumented SYSTEMD_USER_WANTS (see man systemd.device):
ACTION=="change", SUBSYSTEM=="drm", TAG+="systemd", ENV{SYSTEMD_USER_WANTS}="autorandr.service"

Now for some reason that works the first time I plug in the monitor after a reboot, but not after that.

It might have something to do with the following part of the documentation:

Note that systemd will only act on Wants dependencies when a device first becomes active. It will not act on them if they are added to devices that are already active. Use SYSTEMD_READY= (see below) to influence on which udev event to trigger the dependencies.

But I'm not quite sure what that means. I tried asking in the systemd IRC, but didn't get an answer yet.

from autorandr.

phillipberndt avatar phillipberndt commented on May 25, 2024

Yes, it doesn't apply the profile after those logs are shown.

Hmm ok. Please add some debug output to autorandr:

  • After
    print("Running autorandr as %s for display %s" % (pwent.pw_name, display))
    add
    print(process_environ)
    and check whether XAUTHORITY/DISPLAY are set correctly
  • Before
    if "--batch" in options:
    in the main function, add
    print("autorandr started as uid %d" % os.getuid())
  • Also, add --debug to the command line in the systemd unit

This should generate enough info to see what's going on, hopefully.

I'm pretty sure systemd-user works with the same targets as the global systemd.

Just found this as the first result on google. Might have changed in the meantime, of course.

.. SYSTEMD_USER_WANTS ..

That's a really nice feature, and it would be a great solution, but - alas - it won't work. See here, where we found exactly what you did find, too - this only works once.

(A workaround that might work would be to make the systemd unit a service instead of a OneShot script, but write it such that it cleanly stops itself shortly after invocation. Maybe systemd is intelligent enough to see "oh, it's a service, I should restart it because this new device needs it"?!)

from autorandr.

timokau avatar timokau commented on May 25, 2024

Hmm ok. Please add some debug output to autorandr:

I did that, and for some inexplicable reason it just works now. After switching back to the "vanilla" version, it still works.

I'm sorry for bothering you with this, it was probably not working for some other reason. Thanks for the support.

Just found this as the first result on google. Might have changed in the meantime, of course.

Looks like you're right, and thats still the case:

That's a really nice feature, and it would be a great solution, but - alas - it won't work.

We could ask on the systemd mailing list. But if the missing sleep.target is a blocker for systemd-user anyways, that may not be neccessary.

from autorandr.

timokau avatar timokau commented on May 25, 2024

Okay, while I was fiddeling with postswitch scripts it stopped working again.
Here's the output:

-- Logs begin at Mon 2017-08-28 22:21:00 CDT. --
Oct 14 16:02:49 pad systemd[1]: Started autorandr execution hook.
Oct 14 16:03:33 pad systemd[1]: Starting autorandr execution hook...
Oct 14 16:03:34 pad autorandr[26554]: No protocol specified
Oct 14 16:03:34 pad autorandr[26554]: Can't open display :0
Oct 14 16:03:34 pad autorandr[26554]: Failed to run xrandr (line 440)
Oct 14 16:03:34 pad autorandr[26554]: autorandr started as uid 1000
Oct 14 16:03:34 pad autorandr[26554]: autorandr started as uid 0
Oct 14 16:03:34 pad autorandr[26554]: Running autorandr as timo for display :0
Oct 14 16:03:34 pad autorandr[26554]: {'DESKTOP_SESSION': '/nix/store/j93sjhrv8axb4f0nw2ilwcpwagk0s6gi-desktops/none+herbstluftwm', 'DISPLAY': ':0', 'PATH': '/bin:/usr/bin:/usr/local/bin', 'XDG_CURRENT_DESKTOP': '', 'XDG_SEAT': 'seat0', 'XDG_SEAT_PATH': '/org/freedesktop/DisplayManager/Seat0', 'XDG_SESSION_CLASS': 'user', 'XDG_SESSION_DESKTOP': '', 'XDG_SESSION_PATH': '/org/freedesktop/DisplayManager/Session1', 'XDG_SESSION_TYPE': 'x11', 'XDG_VTNR': '7', 'LANG': 'en_US.UTF-8', 'LD_LIBRARY_PATH': '/run/opengl-driver/lib', 'LOCALE_ARCHIVE': '/run/current-system/sw/lib/locale/locale-archive', 'NIX_CONF_DIR': '/etc/nix', 'NIX_OTHER_STORES': '/run/nix/remote-stores/*/nix', 'NIX_PATH': 'nixpkgs=/tmp/:nixos-config=/etc/nixos/configuration.nix:unstable=http://nixos.org/channels/nixos-unstable/nixexprs.tar.xz', 'TZDIR': '/etc/zoneinfo', 'XDG_SESSION_ID': '2', 'XDG_RUNTIME_DIR': '/run/user/1000', 'PAM_KWALLET5_LOGIN': '/run/user/1000/kwallet5.socket', 'AUTORANDR_BATCH_PID': '26554'}
Oct 14 16:03:34 pad systemd[1]: Started autorandr execution hook.

from autorandr.

phillipberndt avatar phillipberndt commented on May 25, 2024

Okay, so the user instance is executed but XAUTHORITY is missing. Interesting: autorandr obtains its environment by scanning through any applications run by your user that have the DISPLAY environment variable set and cloning its environment. Apparently, your user runs a process that has DISPLAY set, but doesn't actually use X11 (It can't without having access..)

To see which process this is, you can add before

print("Running autorandr as %s for display %s" % (pwent.pw_name, display))

the line

print("Copied environment from %s" % " ".join(open(os.path.join(directory, "cmdline")).read().split("\0")))

And to resolve the issue, try adding after

display = process_environ["DISPLAY"] if "DISPLAY" in process_environ else None

a line

if "XAUTHORITY" not in process_environ:
    display = None

from autorandr.

timokau avatar timokau commented on May 25, 2024

"Unfortunately" right now it works again (which makes sense if your explanation is correct: it depends on which process autorandr semi-randomly selects).

Instead I ran the following script to test:

import os

for directory in os.listdir("/proc"):
    directory = os.path.join("/proc/", directory)
    if not os.path.isdir(directory):
        continue
    environ_file = os.path.join(directory, "environ")
    if not os.path.isfile(environ_file):
        continue
    uid = os.stat(environ_file).st_uid

    if uid < 1000:
        continue

    process_environ = {}
    try:
        for environ_entry in open(environ_file).read().split("\0"):
            if "=" in environ_entry:
                name, value = environ_entry.split("=", 1)
                if name == "DISPLAY" and "." in value:
                    value = value[:value.find(".")]
                process_environ[name] = value
        if "DISPLAY" in process_environ and "XAUTHORITY" not in process_environ:
            print("Found %s" % " ".join(open(os.path.join(directory, "cmdline")).read().split("\0")))
    except IOError:
        pass

And got the following results:

Found /nix/store/shq2an5pmbjmgmrjwzn8ixjaxnfspnxj-kwallet-5.37.0-bin/bin/kwalletd5 --
Found /nix/store/rr1vxmwdy7risbsiwcz3iawabnv8w8jn-redshift-1.11/bin/redshift -l xx.yy

I don't know anything about kwalletd5, but redshift is running as a systemd-user service. Maybe that has something to do with it.

Note that I ignored all IOErrors. That's because I got an Permisison denied for /proc/2411/environ. It might be a good idea to handle that case in the real autorandr code.

from autorandr.

phillipberndt avatar phillipberndt commented on May 25, 2024

Interesting that redshift still works - it also uses XRandr to set the gamma curve (e.g.) so it should be restricted by the same ACL as every other process.

However, there should be a simple fix: Prefer processes with XAUTHORITY set as template environments for forking user instances of autorandr. I've made a commit that does this just now.

from autorandr.

timokau avatar timokau commented on May 25, 2024

Yes, that is weird. Maybe it does some hacks to discover XAUTHORITY at runtime.

Your "environment stealing" is a very clever workaround by the way. It might even be worthwhile to extract that to its own script:

for auth in $( detect_running_xsesions ); do
    XAUTHORITY="$auth" autorandr --change
done

or something like that. I could have used that on multiple occasions already (like when trying to notify-send in a cronjob or something).

Thank you for fixing it!

from autorandr.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.