Gentoo Forums
Gentoo Forums
Gentoo Forums
Quick Search: in
Running xmms with higher priority
View unanswered posts
View posts from last 24 hours

Goto page 1, 2  Next  
Reply to topic    Gentoo Forums Forum Index Documentation, Tips & Tricks
View previous topic :: View next topic  
Author Message
how
n00b
n00b


Joined: 29 Jun 2002
Posts: 10
Location: Norway

PostPosted: Mon Jul 29, 2002 1:00 am    Post subject: Running xmms with higher priority Reply with quote

Because only root is allowed to raise the priority (that is, lower the nice value) of a process, I decided to make an xmms wrapper which is simple enough to install setuid root.

The wrapper changes its nice value to -10, drops its privileges and executes the real xmms (which needs to be moved out of the way. It's written in C and looks like this:

Code:
/*
 * This wrapper should be installed setuid root. Move the real xmms
 * executable to e.g. /usr/lib/xmms and install this wrapper in its
 * place.
 *
 * This program will renice itself to -10, then it will drop its root
 * privileges and execute xmms.
 *
 * For security reasons, the path to xmms is hardcoded.
 */

#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/resource.h>

#define XMMS_PATH   "/usr/lib/xmms/xmms"
#define NICE_VALUE   -10

int main( int argc, char **argv )
{
   int result;
   uid_t real_uid;

   result = setpriority( PRIO_PROCESS, getpid(), NICE_VALUE );
   if( result == -1 )
      /* Keep going anyway */
      perror( "xmms-wrapper: Unable to set priority" );
   
   real_uid = getuid();

   /* Drop root privileges. No way back after this */
   result = setuid( real_uid );
   if( result == -1 && errno != EPERM ) {
      /* Is it safe to assume that we won't ever be able to
         higher privileges if we get EPERM here? */
      perror( "xmms-wrapper: Unable to drop privileges" );
      return 1;
   }

   /* Now, execute the real xmms */
   argv[0] = "xmms";
   execv( XMMS_PATH, argv );

   /* If we get this far, something's wrong... */
   perror( "xmms-wrapper: Unable to execute xmms" );
   return 1;
}


Just compile it with you favourite gcc command line (e.g. gcc -O2 -o xmms-wrapper xmms-wrapper.c), move /usr/bin/xmms into /usr/lib/xmms/ and install the wrapper as /usr/bin/xmms. xmms will now run with nice value -10 each time it is started.

This concept should probably be generalized so that programs like mplayer, aviplay, etc. and the X server. Any ideas for a generic implementation?

Also, this concept has the drawback that xmms' visualization plugins run with nice -10 as well. A CPU-hungry plugin could make the system a sluggish. On the other hand, you can easily raise the nice value of the plugin as a normal user.
Back to top
View user's profile Send private message
delta407
Bodhisattva
Bodhisattva


Joined: 23 Apr 2002
Posts: 2876
Location: Chicago, IL

PostPosted: Mon Jul 29, 2002 1:02 am    Post subject: Reply with quote

What does this accomplish? If your CPU is being saturated by some lower-priority task, why not lower its priority instead of increasing the priority of XMMS?
_________________
I don't believe in witty sigs.
Back to top
View user's profile Send private message
how
n00b
n00b


Joined: 29 Jun 2002
Posts: 10
Location: Norway

PostPosted: Mon Jul 29, 2002 1:27 am    Post subject: Reply with quote

delta407 wrote:
What does this accomplish? If your CPU is being saturated by some lower-priority task, why not lower its priority instead of increasing the priority of XMMS?


Good point. But IMHO, audio tasks have real-time requirements (it's annoying when they miss a deadline, i.e. skips), so they deserve higher priority. Besides, you don't have to chase down the offending task.

Compilation processes are obvious candidates for lowering the priority. But with apps like mozilla, which use quite a lot of CPU from time to time, it's not that clear. Lowering the priority of mozilla will most likely reduce the interactive performance. In this situation, I think raising the priority of xmms works best because it has a low and predictable CPU usage.
Back to top
View user's profile Send private message
proxy
Apprentice
Apprentice


Joined: 20 Apr 2002
Posts: 260
Location: Chantilly, VA

PostPosted: Mon Jul 29, 2002 7:53 pm    Post subject: Reply with quote

VERY easy to generalize this. make liberal use of arg[0]. basically my idea is this:

suppse the wrapper gets called like this:

/usr/bin/xmms

instead of using the hard coded line:

Code:

   /* Now, execute the real xmms */
   argv[0] = "xmms";
   execv( XMMS_PATH, argv );


you can change that to somthing like this: (may not work exactly, just pseudo code)

Code:


    char realPath[MAX_PATH] = "/usr/lib/";

    char *realName = argv[0];
    char *lastSlash = strrchr(realName, '/');
    if(lastSlash) {
        realName = lastSlash + 1;
    }

    strcat(realPath, realName);

    argv[0] = realPath;
    execv( XMMS_PATH, argv );


this way in order to make it work for ANY executable, you can have a single binary (/usr/bin/run_nice) and have that symlinked to the name of the program you really wanna run like this:

mv /usr/bin/xmms /usr/lib/xmms
ln -s /usr/bin/run_nice /usr/bin/xmms

if i was unclear let me know....my only worry would be the scope of my "realPath" variable running out, but i am sure that can be easily worked out ;)

proxy
Back to top
View user's profile Send private message
proxy
Apprentice
Apprentice


Joined: 20 Apr 2002
Posts: 260
Location: Chantilly, VA

PostPosted: Mon Jul 29, 2002 8:22 pm    Post subject: Reply with quote

hmm, i do see a bit of a security concern with my idea though. assuming a regular user manages to copy a program to /usr/local/lib which you dont want them to running with a nice value of -10 they could just make a symlink and start running it.

considering that you need root to create stuiff in /usr/local/lib anyway, is this a big deal?

proxy
Back to top
View user's profile Send private message
proxy
Apprentice
Apprentice


Joined: 20 Apr 2002
Posts: 260
Location: Chantilly, VA

PostPosted: Mon Jul 29, 2002 8:28 pm    Post subject: Reply with quote

just to make my idea 100% clear, here's working implementation based on yours which is completely generic:

Code:

/*
* This wrapper should be installed setuid root.  Move the real
* executable to eg. /usr/local/lib and install a symlink to this
* wrapper in its place
*
* this program will renice itself to -10, the it will drop its root
* privileges and execuate the real program.
*/

#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/resource.h>

#define REAL_PATH "/usr/local/lib"
#define NEW_NICE -10
#define MAX_PATH 255

int main(int argc, char *argv[]) {
    int result;
    uid_t real_uid;
    char real_path[MAX_PATH] = "/usr/local/lib/";
    char *realName = argv[0];
    char *lastSlash = NULL;
   
    result = setpriority(PRIO_PROCESS, getpid(), NEW_NICE);
    if(result == -1) {
        /* keep going anyway */
        perror("unable to set priority.");
    }
   
    real_uid = getuid();
   
    /* Drop root privileges. nop way back after this */
    result = setuid(real_uid);
    if(result == -1 && errno != EPERM) {
        /* is it safe to assume we wont ever be able to
           higher privileges if we get EPERM here? */
        perror("unable to drop privileges");
        return 1;
           
    }
   
   
    lastSlash = strrchr(realName, '/');   
    if(lastSlash) {
        realName = (lastSlash + 1);
    }
   
    strncat(real_path, realName, MAX_PATH - strlen(real_path));
   
    argv[0] = real_path;
    execv(real_path, argv);

    perror("unable to execute program.");
    return 1;
   
    return 0;
   
}


so basically you install this binary "run_nice" into /usr/bin, then move the real one to /usr/local/lib, then finally symlink /usr/bin/run_nice to the name of the original program (eg: /usr/bin/xmms => /usr/bin/runnice)

i'd say ideally it would be sweet to have some sort of config file specifying which binaries were allowed to be run with this and what priority they should get :)

i think i'm gonna implement that and post in a few days ;)

that would be much more secure.

proxy
Back to top
View user's profile Send private message
delta407
Bodhisattva
Bodhisattva


Joined: 23 Apr 2002
Posts: 2876
Location: Chicago, IL

PostPosted: Mon Jul 29, 2002 8:35 pm    Post subject: Reply with quote

What happens when you:

Code:
# cp /usr/bin/run_nice /usr/local/lib/run_nice
# run_nice


:?:
_________________
I don't believe in witty sigs.
Back to top
View user's profile Send private message
proxy
Apprentice
Apprentice


Joined: 20 Apr 2002
Posts: 260
Location: Chantilly, VA

PostPosted: Mon Jul 29, 2002 8:56 pm    Post subject: Reply with quote

hehe, well dont do that :)

yea, that a pretty bad recursion error, and unfortunately there is no _really_ easy fix for it either. cause you can rename the execuatable to whatever you like.

I suppose for now the best advice i can give is "don't do that" until i think of a clever way to prevent that. most likely there will have to be some sort of "recusion detection" or some bizarre way to detect that the program it is executing is in fact a copy of itself...but now this little util is getting kinda heavy :P

any ideas to prevent that?

I'd say off hand, the easiest solution would be to throw 1 extra param into argv saying "this was run with run_nice, dont execute"..but how would i gaurantee that no programs use such a value :(

hrmm......

proxy
Back to top
View user's profile Send private message
how
n00b
n00b


Joined: 29 Jun 2002
Posts: 10
Location: Norway

PostPosted: Mon Jul 29, 2002 9:44 pm    Post subject: Reply with quote

proxy wrote:
any ideas to prevent that?

I'd say off hand, the easiest solution would be to throw 1 extra param into argv saying "this was run with run_nice, dont execute"..but how would i gaurantee that no programs use such a value :(


Use an environment variable perhaps? We'll still have the trouble of finding a unique name for it, though.

How about this: Set $RUN_NICE_PID to the current process' PID value before executing the real program. If $RUN_NICE_PID equals current process' PID value on startup, just terminate. :?:

I don't know if it might be better just to check for the existence of the variable. If we check the PID, we might be able to do the right thing in some situations when some run_nice'd program spawns another run_nice'd program (the $RUN_NICE_PID variable will still be around when executing the second program, and we do want to run it).
Back to top
View user's profile Send private message
delta407
Bodhisattva
Bodhisattva


Joined: 23 Apr 2002
Posts: 2876
Location: Chicago, IL

PostPosted: Mon Jul 29, 2002 10:57 pm    Post subject: Reply with quote

how wrote:
How about this: Set $RUN_NICE_PID to the current process' PID value before executing the real program. If $RUN_NICE_PID equals current process' PID value on startup, just terminate. :?:


That ought to work. IIRC execv preserves the PID.

Also, why do you have:

Code:
return 1;

return 0;
:?:
_________________
I don't believe in witty sigs.
Back to top
View user's profile Send private message
proxy
Apprentice
Apprentice


Joined: 20 Apr 2002
Posts: 260
Location: Chantilly, VA

PostPosted: Tue Jul 30, 2002 12:33 am    Post subject: Reply with quote

well that would be a cut and paste error :P

i always stub out my main like this:

Code:

int main(int argc, char *argv[]) {
    return 0;
}


then fill in the rest, i simply pasted his code into mine and forgot to remove my return 0; it can obviously be removed
Back to top
View user's profile Send private message
Mnemia
Guru
Guru


Joined: 17 May 2002
Posts: 476

PostPosted: Fri Oct 18, 2002 8:12 am    Post subject: Reply with quote

Sorry to dredge up an old thread, but I was just looking into how to solve the constant skipping in XMMS I've been experiencing, and I still haven't really totally solved the problem.

I'm still experiencing some skipping even when I'm running a niced emerge process, a niced (priority 25) mozilla 1.1, and XMMS with it's priority bumped up to -10! Really the only other things I'm running when this happens are fluxbox and X. The skipping occurs usually when Mozilla is laying out a new page or something. The nice settings help to reduce the frequency and length of the skipping, but do not eliminate it totally.

I'm inclined to think that it's hard drive related, though, because I've had some annoying issues with the Hitachi hard drive in this laptop. It seems that my system sometimes "jumps" or "hangs" momentarily (just like a quarter second) when it initiates writes, and my guess is that it's doing this when Mozilla writes to its cache. I think I've got my hdparm settings set right though because the drive has very good throughput for reading and writing...it just tends to creates latency in the system.

IBM Thinkpad A30, 1.13 Ghz PIII, 384 MB RAM, 30 GB HITACHI_DK23DA-30B hard disk.

BTW...I'm still running a GCC2.95 system because I just haven't had the time or desire to upgrade yet. This could well be the thing that gets me to move to that whole new set of hassles if you all think that the new optimizations in 3.2 would help with this.
Back to top
View user's profile Send private message
OdinsDream
Veteran
Veteran


Joined: 01 Jun 2002
Posts: 1057

PostPosted: Sat Oct 26, 2002 5:09 am    Post subject: Reply with quote

To solve the recursion, isn't one of the command-line arguments available to a program at runtime....also the name of the program that is running?

I seem to remember running into this before.

For instance:

tail -f someFile

would create

argv[0] == "tail"
argv[1] == "-f"
argv[2] == "someFile"

Therefore, could you simply check if argv[0] == argv[2] (or something slightly more complex..) to see whether or not the user tried to run this script with itself?
Back to top
View user's profile Send private message
proxy
Apprentice
Apprentice


Joined: 20 Apr 2002
Posts: 260
Location: Chantilly, VA

PostPosted: Sat Oct 26, 2002 5:27 am    Post subject: Reply with quote

hehe, it's always the simple solutions :P

i'll give it a try and possibly post a "final" version of this program :)

proxy
Back to top
View user's profile Send private message
proxy
Apprentice
Apprentice


Joined: 20 Apr 2002
Posts: 260
Location: Chantilly, VA

PostPosted: Sat Oct 26, 2002 5:34 am    Post subject: Reply with quote

wait a sec, my version did not get the program to be run from the argument list, it got it from the name it was called under (the idea being that you just symlink the original run_nice to the program name you wanna run and move the original of that program to /usr/local/lib like this:

# mv /usr/bin/xmms /usr/local/lib
# ln -s /usr/bin/run_nice /usr/bin/xmms
# xmms

would run the xmms niced to -10, oh well i knew it couldn't be that simple :P

proxy
Back to top
View user's profile Send private message
zenon
Apprentice
Apprentice


Joined: 09 Oct 2002
Posts: 263

PostPosted: Tue Feb 11, 2003 7:09 am    Post subject: Reply with quote

I'm having skipping probs too, is there a final version of the script or another way of making XMMS less nice for non-root users (preferably always and automatically)

thnx.
Back to top
View user's profile Send private message
Matje
l33t
l33t


Joined: 29 Oct 2002
Posts: 619
Location: Hasselt, Belgium

PostPosted: Tue Feb 11, 2003 1:18 pm    Post subject: Reply with quote

Please make sure you have DMA and 32-bit mode enabled for your harddrive...
Code:
# hdparm -c -d /dev/hda
 
/dev/hda:
 IO_support   =  1 (32-bit)
 using_dma    =  1 (on)


Enable it with:
Code:
# hdparm -c1 -d1 /dev/hda

There is an init-script to do this for you (I edited it to include 32-bit support)...
_________________
Life is like a box of chocolates... Before you know it, it's empty...
Back to top
View user's profile Send private message
zenon
Apprentice
Apprentice


Joined: 09 Oct 2002
Posts: 263

PostPosted: Tue Feb 11, 2003 11:15 pm    Post subject: Reply with quote

I have done hparm settings B4, do they need to be re-done everytime you reboot?
Back to top
View user's profile Send private message
kraylus
l33t
l33t


Joined: 07 Jun 2002
Posts: 648
Location: ft.worth.tx

PostPosted: Wed Feb 12, 2003 12:23 am    Post subject: Reply with quote

zenon wrote:
I have done hparm settings B4, do they need to be re-done everytime you reboot?


to my knowledge yes. put the command in /etc/conf.d/local.start
_________________
I used gentoo BEFORE it was cool.
Back to top
View user's profile Send private message
zenon
Apprentice
Apprentice


Joined: 09 Oct 2002
Posts: 263

PostPosted: Wed Feb 12, 2003 1:36 am    Post subject: Reply with quote

When does that start? I'd be nice to run that command 1st so booting would be quicker..

hmm, a B4 and after delta was 10 times quicker.... maybe that's my problem :-o
Back to top
View user's profile Send private message
zenon
Apprentice
Apprentice


Joined: 09 Oct 2002
Posts: 263

PostPosted: Thu Feb 13, 2003 7:17 am    Post subject: Reply with quote

I did the DMA thing on all my drives (2HDD's and a CDR) and ALL hiccups have been cured!!

Even the USB HID mouse lag that was annoying me to no end (even after switching to the ck sources [GOD I LOVE THIS KERNEL]) is devoid and defunct.

Appz are loading faster and everything is cooking along nicely :)
That file is one of the 1st to load (It is even where I call the HID module) so hopefully it will speed my startup too.
Back to top
View user's profile Send private message
Matje
l33t
l33t


Joined: 29 Oct 2002
Posts: 619
Location: Hasselt, Belgium

PostPosted: Thu Feb 13, 2003 5:33 pm    Post subject: Reply with quote

You can edit /etc/init.d/hdparm to reflect your options, just add them to the hdparm commandline. Then do:
Code:
rc-update add hdparm boot

This way it'll be started way before everything else starts, resulting in (little) faster boot. You can also add it to local.start like kraylus said, but then it'll be done at the very end of inittime...
_________________
Life is like a box of chocolates... Before you know it, it's empty...
Back to top
View user's profile Send private message
Redneck
n00b
n00b


Joined: 01 Nov 2002
Posts: 7
Location: Belgium

PostPosted: Sun Aug 31, 2003 5:44 pm    Post subject: Reply with quote

Any way to make this work when GTK refuses to run setuid wrappers? :)

tnx
Back to top
View user's profile Send private message
meowsqueak
Veteran
Veteran


Joined: 26 Aug 2003
Posts: 1549
Location: New Zealand

PostPosted: Mon Sep 01, 2003 5:15 am    Post subject: Reply with quote

You could use a script like this:

Code:
#!/bin/sh
/usr/bin/renice -10 $$
/usr/bin/xmms $@ &
# drop privileges here


Begging the question that such a 'drop privileges' command exists for a shell script, this should work I think. If such a 'drop privileges' shell function/command exists, what is it? Anyone know?
Back to top
View user's profile Send private message
Redneck
n00b
n00b


Joined: 01 Nov 2002
Posts: 7
Location: Belgium

PostPosted: Mon Sep 01, 2003 10:13 am    Post subject: Reply with quote

Works, standalone single user system, security can be a bit lower ;)

tnx
Back to top
View user's profile Send private message
Display posts from previous:   
Reply to topic    Gentoo Forums Forum Index Documentation, Tips & Tricks All times are GMT
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum