Different method of bumping priority.

Calling nice() in the very beginning ensures that Mesa worker threads in
gamescope and Xwayland can properly reduce their priority without us stomping
it later.

Move away from posix_spawn, since there's no easy way (that seems to work)
to keep priority normal for the spawned process and get the right behaviour
for gamescope and Xwayland.

The intermediate fork() lets us simplify the logic for LD_PRELOAD rewriting.
This commit is contained in:
Pierre-Loup A. Griffais 2020-09-02 11:02:31 -07:00
parent f70308a36f
commit e1d4937310
3 changed files with 64 additions and 67 deletions

View file

@ -35,6 +35,8 @@ bool g_bBorderlessOutputWindow = false;
bool g_bTakeScreenshot = false;
bool g_bNiceCap = false;
int g_nOldNice = 0;
int g_nNewNice = 0;
uint32_t g_nSubCommandArg = 0;
@ -115,7 +117,6 @@ int main(int argc, char **argv)
strPreviousR600Debug.append( ",nodcc" );
setenv( "R600_DEBUG", strPreviousR600Debug.c_str(), 1 );
}
}
cap_t caps;
@ -129,6 +130,20 @@ int main(int argc, char **argv)
if ( nicecapvalue == CAP_SET )
{
g_bNiceCap = true;
errno = 0;
int nOldNice = nice( 0 );
if ( nOldNice != -1 && errno == 0 )
{
g_nOldNice = nOldNice;
}
errno = 0;
int nNewNice = nice( -20 );
if ( nNewNice != -1 && errno == 0 )
{
g_nNewNice = nNewNice;
}
}
}

View file

@ -25,5 +25,7 @@ extern bool g_bTakeScreenshot;
extern uint32_t g_nSubCommandArg;
extern bool g_bNiceCap;
extern int g_nOldNice;
extern int g_nNewNice;
int BIsNested( void );

View file

@ -2640,56 +2640,35 @@ steamcompmgr_main (int argc, char **argv)
if ( g_nSubCommandArg != 0 )
{
pid_t pid;
sigset_t fullset;
sigfillset( &fullset );
posix_spawnattr_t attr;
posix_spawnattr_init( &attr );
posix_spawnattr_setflags( &attr, POSIX_SPAWN_SETSIGDEF );
posix_spawnattr_setsigdefault( &attr, &fullset );
// Put the children in their own thread group to avoid setpriority below
posix_spawnattr_setflags( &attr, POSIX_SPAWN_SETPGROUP );
posix_spawnattr_setpgroup( &attr, 0 );
// (Don't Lose) The Children
prctl( PR_SET_CHILD_SUBREAPER );
std::vector< char * > vecNewEnviron;
char ** oldEnviron = environ;
while ( *oldEnviron != nullptr )
{
size_t envLength = strlen( *oldEnviron ) + 1;
char *envVar = new char[ envLength ];
std::string strNewPreload;
char *pchPreloadCopy = nullptr;
const char *pchCurrentPreload = getenv( "LD_PRELOAD" );
bool bFirst = true;
strcpy( envVar, *oldEnviron );
if ( pchCurrentPreload != nullptr )
{
pchPreloadCopy = strdup( pchCurrentPreload );
if ( strstr( envVar, "LD_PRELOAD=" ) == envVar )
// First replace all the separators in our copy with terminators
for ( uint32_t i = 0; i < strlen( pchCurrentPreload ); i++ )
{
std::string strNewPreload = "LD_PRELOAD=";
// First replace all the separators in our temporary copy with terminators
for ( char *c = &envVar[ 11 ]; c < envVar + envLength; c++ )
if ( pchPreloadCopy[ i ] == ' ' || pchPreloadCopy[ i ] == ':' )
{
if ( *c == ' ' || *c == ':' )
{
*c = '\0';
pchPreloadCopy[ i ] = '\0';
}
}
// Then walk it again and find all the substrings
for ( char *c = &envVar[ 11 ]; c < envVar + envLength; c++ )
uint32_t i = 0;
while ( i < strlen( pchCurrentPreload ) )
{
// If there's a string and it's not gameoverlayrenderer, append it to our new LD_PRELOAD
if ( *c != '\0' )
if ( pchPreloadCopy[ i ] != '\0' )
{
if ( strstr( c, "gameoverlayrenderer.so" ) == nullptr )
if ( strstr( pchPreloadCopy + i, "gameoverlayrenderer.so" ) == nullptr )
{
if ( bFirst == false )
{
@ -2700,34 +2679,40 @@ steamcompmgr_main (int argc, char **argv)
bFirst = false;
}
strNewPreload.append( c );
strNewPreload.append( pchPreloadCopy + i );
}
c += strlen ( c );
i += strlen ( pchPreloadCopy + i );
}
}
// Then copy back to our allocated string, it has to be strictly larger than the original
strcpy( envVar, strNewPreload.c_str() );
}
vecNewEnviron.push_back( envVar );
oldEnviron++;
}
vecNewEnviron.push_back( nullptr ) ;
posix_spawnp( &pid, argv[ g_nSubCommandArg ], NULL, &attr, &argv[ g_nSubCommandArg ], vecNewEnviron.data() );
for ( uint32_t i = 0; i < vecNewEnviron.size(); i++ )
else
{
if ( vecNewEnviron[ i ] != nullptr )
{
delete[] vecNewEnviron[ i ];
i++;
}
}
free( pchPreloadCopy );
}
pid_t pid = fork();
// Are we in the child?
if ( pid == 0 )
{
// Try to snap back to old priority
if ( g_bNiceCap == true )
{
nice( g_nOldNice - g_nNewNice );
}
// Set modified LD_PRELOAD
if ( strNewPreload.empty() == false )
{
setenv( "LD_PRELOAD", strNewPreload.c_str(), 1 );
}
execvp( argv[ g_nSubCommandArg ], &argv[ g_nSubCommandArg ] );
}
std::thread waitThread([](){
while( wait( nullptr ) >= 0 )
{
@ -2743,11 +2728,6 @@ steamcompmgr_main (int argc, char **argv)
std::thread imageWaitThread( imageWaitThreadRun );
imageWaitThread.detach();
if ( g_bNiceCap == true )
{
setpriority( PRIO_PGRP, getpid(), -20 );
}
for (;;)
{
focusDirty = False;