How to add space to formatting - string-formatting
Im new to coding, and found a script that writes the song and artist into a txt file called PlayLog.txt. When i use the script, it works as intended, however I do not know how to add space to the end of the output.
so instead of "[song] by [artist]" I would like "[song] by [artist] + 8 spaces"
that way the scrolling text in my OBS doesnt merge the end of the artist with the beginning of the song.
; This script displays the currently playing song from the pandora one app
;
; Any future updates can be found at http://notunusual.net/pandoraone_autohotkey/
;
; This function relies heavily on the excellent tray icon script by Sean, the original version
; of these functions can be found here - http://www.autohotkey.com/forum/topic17314.html
;
; Updates to the tray icon functions originally by Fanatic Guru, as per the following link:
; http://www.autohotkey.com/board/topic/94573-autohotkey-startup-consolidate-ahk-scripts-tray-icons/?p=595938
;
; Further updates to the tray icon functions and to this script in general by RiseUp.
; Make the script work even if the window is hidden
DetectHiddenWindows, on
; Only allow a single instance of the script
#SingleInstance
LogFileDir := A_AppData . "\notunusual\PandoraOne\"
LogFile := LogFileDir . "PlayLog.txt"
FileCreateDir, %LogFileDir%
if (ErrorLevel = 1)
{
MsgBox "Error creating directory!"
}
prevArtist := ""
prevSong := ""
while (true)
{
GetCurrentPlayingSong(curSong, curArtist)
if (((curSong <> prevSong) or (curArtist <> prevArtist)) and ((curSong <> "") and (curArtist <> "")))
{
prevSong := curSong
prevArtist := curArtist
FileDelete, %LogFile%
if ErrorLevel
MsgBox, Error deleting PlayLog.txt!
FileAppend %prevSong% by %prevArtist%, %LogFile%
}
; This is how often a check will be done, a sleep of 1000 means every 1 second we'll check the value
Sleep, 1000
}
; This returns the current song in the format Song by Artist, this can easily be changed to
; whatever format is desired
GetCurrentPlayingSong(ByRef songName, ByRef artist, space)
{
TI := TrayIconsSearch("Pandora.exe")
StringSplit,TIV, TI, |
toolTip := RegExReplace(TIV9, "Tooltip: ")
StringSplit, toolTipArray, toolTip, `n
songName := toolTipArray2
artist := RegExReplace( toolTipArray3, "by " )
}
TrayIconsSearch(sTerm)
{
Tray_Icons := {}
Tray_Icons := TrayIcons(sTerm)
if A_OSVersion in WIN_VISTA,WIN_7,WIN_8
{
arr := {}
arr := TrayIconsOverflow(sTerm)
for index, element in arr
Tray_Icons.Insert(element)
arr := ""
}
for index, element in Tray_Icons
sTrayIcons .= "idx: " . element.idx . " | idn: " . element.idn . " | Pid: " . element.pid . " | uID: " . element.uID . " | MessageID: " . element.MessageID . " | hWnd: " . element.hWnd . " | Class: " . element.Class . " | Process: " . element.Process . "`n" . " | Tooltip: " . element.Tooltip . "`n`n"
Return sTrayIcons
}
TrayIcons(sExeName = "")
{
arr := {}
Setting_A_DetectHiddenWindows := A_DetectHiddenWindows
DetectHiddenWindows, On
WinGet, pidTaskbar, PID, ahk_class Shell_TrayWnd
hProc:= DllCall("OpenProcess", "Uint", 0x38, "int", 0, "Uint", pidTaskbar)
pProc:= DllCall("VirtualAllocEx", "Uint", hProc, "Uint", 0, "Uint", 32, "Uint", 0x1000, "Uint", 0x4)
idxTB:= GetTrayBar()
SendMessage, 0x418, 0, 0, ToolbarWindow32%idxTB%, ahk_class Shell_TrayWnd ; TB_BUTTONCOUNT
Loop, %ErrorLevel%
{
SendMessage, 0x417, A_Index-1, pProc, ToolbarWindow32%idxTB%, ahk_class Shell_TrayWnd ; TB_GETBUTTON
VarSetCapacity(btn,32,0), VarSetCapacity(nfo,32,0)
DllCall("ReadProcessMemory", "Uint", hProc, "Uint", pProc, "Uint", &btn, "Uint", 32, "Uint", 0)
iBitmap := NumGet(btn, 0)
idn := NumGet(btn, 4)
Statyle := NumGet(btn, 8)
If dwData := NumGet(btn,12,"Uint")
iString := NumGet(btn,16)
Else dwData := NumGet(btn,16,"int64"), iString:=NumGet(btn,24,"int64")
DllCall("ReadProcessMemory", "Uint", hProc, "Uint", dwData, "Uint", &nfo, "Uint", 32, "Uint", 0)
If NumGet(btn,12,"Uint")
hWnd := NumGet(nfo, 0)
, uID := NumGet(nfo, 4)
, nMsg := NumGet(nfo, 8)
, hIcon := NumGet(nfo,20)
Else hWnd := NumGet(nfo, 0,"int64"), uID:=NumGet(nfo, 8,"Uint"), nMsg:=NumGet(nfo,12,"Uint")
WinGet, pid, PID, ahk_id %hWnd%
WinGet, sProcess, ProcessName, ahk_id %hWnd%
WinGetClass, sClass, ahk_id %hWnd%
If !sExeName || (sExeName = sProcess) || (sExeName = pid)
VarSetCapacity(sTooltip,128), VarSetCapacity(wTooltip,128*2)
, DllCall("ReadProcessMemory", "Uint", hProc, "Uint", iString, "Uint", &wTooltip, "Uint", 128*2, "Uint", 0)
, DllCall("WideCharToMultiByte", "Uint", 0, "Uint", 0, "str", wTooltip, "int", -1, "str", sTooltip, "int", 128, "Uint", 0, "Uint", 0)
, Index = arr.MaxIndex()>0 ? arr.MaxIndex()+1 : 1
, arr[Index,"idx"] := A_Index-1
, arr[Index,"idn"] := idn
, arr[Index,"Pid"] := Pid
, arr[Index,"uID"] := uID
, arr[Index,"MessageID"] := nMsg
, arr[Index,"hWnd"] := hWnd
, arr[Index,"Class"] := sClass
, arr[Index,"Process"] := sProcess
, arr[Index,"Tooltip"] := (A_IsUnicode ? wTooltip : sTooltip)
}
DllCall("VirtualFreeEx", "Uint", hProc, "Uint", pProc, "Uint", 0, "Uint", 0x8000)
DllCall("CloseHandle", "Uint", hProc)
DetectHiddenWindows, %Setting_A_DetectHiddenWindows%
Return arr
}
TrayIconsOverflow(sExeName = "")
{
arr := {}
Setting_A_DetectHiddenWindows := A_DetectHiddenWindows
DetectHiddenWindows, On
WinGet, pidTaskbar, PID, ahk_class NotifyIconOverflowWindow
hProc:= DllCall("OpenProcess", "Uint", 0x38, "int", 0, "Uint", pidTaskbar)
pProc:= DllCall("VirtualAllocEx", "Uint", hProc, "Uint", 0, "Uint", 32, "Uint", 0x1000, "Uint", 0x4)
idxTB:= 1
SendMessage, 0x418, 0, 0, ToolbarWindow32%idxTB%, ahk_class NotifyIconOverflowWindow ; TB_BUTTONCOUNT
Loop, %ErrorLevel%
{
SendMessage, 0x417, A_Index-1, pProc, ToolbarWindow32%idxTB%, ahk_class NotifyIconOverflowWindow ; TB_GETBUTTON
VarSetCapacity(btn,32,0), VarSetCapacity(nfo,32,0)
DllCall("ReadProcessMemory", "Uint", hProc, "Uint", pProc, "Uint", &btn, "Uint", 32, "Uint", 0)
iBitmap := NumGet(btn, 0)
idn := NumGet(btn, 4)
Statyle := NumGet(btn, 8)
If dwData := NumGet(btn,12,"Uint")
iString := NumGet(btn,16)
Else dwData := NumGet(btn,16,"int64"), iString:=NumGet(btn,24,"int64")
DllCall("ReadProcessMemory", "Uint", hProc, "Uint", dwData, "Uint", &nfo, "Uint", 32, "Uint", 0)
If NumGet(btn,12,"Uint")
hWnd := NumGet(nfo, 0)
, uID := NumGet(nfo, 4)
, nMsg := NumGet(nfo, 8)
, hIcon := NumGet(nfo,20)
Else hWnd := NumGet(nfo, 0,"int64"), uID:=NumGet(nfo, 8,"Uint"), nMsg:=NumGet(nfo,12,"Uint")
WinGet, pid, PID, ahk_id %hWnd%
WinGet, sProcess, ProcessName, ahk_id %hWnd%
WinGetClass, sClass, ahk_id %hWnd%
If !sExeName || (sExeName = sProcess) || (sExeName = pid)
VarSetCapacity(sTooltip,128), VarSetCapacity(wTooltip,128*2)
, DllCall("ReadProcessMemory", "Uint", hProc, "Uint", iString, "Uint", &wTooltip, "Uint", 128*2, "Uint", 0)
, DllCall("WideCharToMultiByte", "Uint", 0, "Uint", 0, "str", wTooltip, "int", -1, "str", sTooltip, "int", 128, "Uint", 0, "Uint", 0)
, Index = arr.MaxIndex()>0 ? arr.MaxIndex()+1 : 1
, arr[Index,"idx"] := A_Index-1
, arr[Index,"idn"] := idn
, arr[Index,"Pid"] := Pid
, arr[Index,"uID"] := uID
, arr[Index,"MessageID"] := nMsg
, arr[Index,"hWnd"] := hWnd
, arr[Index,"Class"] := sClass
, arr[Index,"Process"] := sProcess
, arr[Index,"Tooltip"] := (A_IsUnicode ? wTooltip : sTooltip)
}
DllCall("VirtualFreeEx", "Uint", hProc, "Uint", pProc, "Uint", 0, "Uint", 0x8000)
DllCall("CloseHandle", "Uint", hProc)
DetectHiddenWindows, %Setting_A_DetectHiddenWindows%
Return arr
}
GetTrayBar()
{
ControlGet, hParent, hWnd,, TrayNotifyWnd1 , ahk_class Shell_TrayWnd
ControlGet, hChild , hWnd,, ToolbarWindow321, ahk_id %hParent%
Loop
{
ControlGet, hWnd, hWnd,, ToolbarWindow32%A_Index%, ahk_class Shell_TrayWnd
If Not hWnd
Break
Else If hWnd = %hChild%
{
idxTB := A_Index
Break
}
}
Return idxTB
}
Well... I'll bite. Here's the code you need to modify.
FileAppend %prevSong% by %prevArtist%, %LogFile%
Here's how I would modify it.
NewVar := prevSong . " by " . prevArtist . " "
FileAppend %NewVar%, %LogFile%
FYI, there were examples of this method in the code itself if you studied it for a moment you would see it.
Related
X11 Shift + Tab keysym?
How to detect Shift + Tab in Xlib? I'm able to match KeySym with XK_Tab, but it's not matching while holding shift to then check for ev->state & ShiftMask, so I'm kind of lost. SOLUTION: Thanks to Erdal Küçük's answer I was able to come up with the following function that detects Shift + Tab: int detectShiftTab(XKeyEvent *xkey) { return XLookupKeysym(xkey, 0) == XK_Tab && xkey->state & ShiftMask; }
With a simple test, i realized that the ShiftMask is not reported on a KeyPress of the Shift key. Other than that, the ShiftMask is always set. int main() { Display *dpy = XOpenDisplay(NULL); Window win = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 0, 0, 640, 480, 0, 0, 0); XSetWindowAttributes attr = { .event_mask = (KeyPressMask | KeyReleaseMask) }; XChangeWindowAttributes(dpy, win, CWEventMask, &attr); XMapWindow(dpy, win); while (1) { XEvent evt; XNextEvent(dpy, &evt); switch (evt.type) { case KeyPress: printf( "key press: %s shiftmask: %d\n", XKeysymToString(XLookupKeysym(&evt.xkey, 0)), (evt.xkey.state & ShiftMask) == ShiftMask ); break; case KeyRelease: printf( "key release: %s shiftmask: %d\n", XKeysymToString(XLookupKeysym(&evt.xkey, 0)), (evt.xkey.state & ShiftMask) == ShiftMask ); break; } } return 0; } I get the following output (typing Shift + Tab): key press: Shift_L shiftmask: 0 key press: Tab shiftmask: 1 key release: Tab shiftmask: 1 key release: Shift_L shiftmask: 1
why doesn't the OpenCL kernel execute even though there are no errors? (c, nvidia, kubuntu)
I'm learning opencl and for some reason the kernel does nothing: #include <stdlib.h> #include <stdio.h> #define CL_TARGET_OPENCL_VERSION 300 #include <CL/cl.h> int err = 0; #define PRINTERR() fprintf(stderr, "Error at line %u.\n", __LINE__) #define CHECKERR(x) if(x){PRINTERR();return __LINE__;} #define CHECKNOTERR(x) if(!x){PRINTERR();return __LINE__;} const char *KernelSource = "__kernel void square( \n" \ " __global float* input, \n" \ " __global float* output, \n" \ " const unsigned int count) \n" \ "{ \n" \ " int i = get_global_id(0); \n" \ " if(i == 0) printf(\"test\\n\"); \n" \ " if(i < count) \n" \ " output[i] = input[i] * input[i]; \n" \ "} \n" ; #define DATA_SIZE 1024 int main(){ float data[DATA_SIZE]; float results[DATA_SIZE]; size_t global; size_t local; cl_platform_id platform_id; cl_device_id device_id; cl_context context; cl_command_queue commands; cl_program program; cl_kernel kernel; cl_mem input; cl_mem output; unsigned int i = 0; unsigned int count = DATA_SIZE; for(i = 0; i < count; ++i) //data[i] = rand() / (float)RAND_MAX; data[i] = 2.f; int gpu = 1; err = clGetPlatformIDs (1, &platform_id, NULL); CHECKERR(err) err = clGetDeviceIDs(platform_id, gpu ? CL_DEVICE_TYPE_GPU : CL_DEVICE_TYPE_CPU, 1, &device_id, NULL); CHECKERR(err) context = clCreateContext(NULL, 1, &device_id, NULL, NULL, &err); CHECKERR(!context) commands = clCreateCommandQueueWithProperties(context, device_id, NULL, &err); CHECKERR(err) input = clCreateBuffer(context, CL_MEM_READ_ONLY, sizeof(float) * count, NULL, &err); CHECKERR(err) output = clCreateBuffer(context, CL_MEM_WRITE_ONLY, sizeof(float) * count, NULL, &err); CHECKERR(err) CHECKERR(!input || !output) err = clEnqueueWriteBuffer(commands, input, CL_TRUE, 0, sizeof(float) * count, data, 0, NULL, NULL); CHECKERR(err) program = clCreateProgramWithSource(context, 1, &KernelSource, NULL, &err); CHECKERR(err) err = clBuildProgram(program, 1, &device_id, NULL, NULL, NULL); CHECKERR(err) kernel = clCreateKernel(program, "square", &err); CHECKERR(err) err = clSetKernelArg(kernel, 0, sizeof(cl_mem), &input); err |= clSetKernelArg(kernel, 1, sizeof(cl_mem), &output); err |= clSetKernelArg(kernel, 2, sizeof(unsigned int), &count); CHECKERR(err) err = clGetKernelWorkGroupInfo(kernel, device_id, CL_KERNEL_WORK_GROUP_SIZE, sizeof(local), &local, NULL); CHECKERR(err) err = clEnqueueNDRangeKernel(commands, kernel, 1, NULL, &global, &local, 0, NULL, NULL); CHECKERR(err) err = clEnqueueReadBuffer(commands, output, CL_TRUE, 0, sizeof(float) * count, results, 0, NULL, NULL ); CHECKERR(err) clFlush(commands); clFinish(commands); unsigned int correct = 0; for(i = 0; i < count; ++i) printf("%f\n",results[i]); printf("Computed '%d/%d' correct values!\n", correct, count); // free clReleaseMemObject(input); clReleaseMemObject(output); clReleaseKernel(kernel); clReleaseProgram(program); clReleaseCommandQueue(commands); clReleaseContext(context); return 0; } i want it to do things, but it doesn't. i tried reading the input instead of the output and it goes fine. the printf in the kernel does nothing and if i run it clEnqueueReadBuffer gives just 0. i have an amd, so i can't test it on the cpu. i tried another example and it worked. (the one here) help appreciated.
global is 0, so the program runs 0 times.
How do I fix a CL_INVALID_MEM_OBJECT when I pass a buffer to an OpenCL kernel and the buffer is from clCreateFromGLTexture?
I need to do some math on the pixels of a GL texture. I have a working OpenCL kernel. I can convert the GL texture to an OpenCL buffer (at least, it doesn't give an error). But when I try to set that buffer as an argument to the kernel I get error -38 (CL_INVALID_MEM_OBJECT). I originally tried it using rust, but when that was failing, I switched to C just to see if the problem existed independent of rust's wrappers. This is my C app that is duct taped together from a couple of examples (c++ -g -o check2 check2.cxx -lOpenCL -lGL -lX11): /* https://www.khronos.org/opengl/wiki/Tutorial:_OpenGL_3.0_Context_Creation_(GLX) */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <X11/Xlib.h> #include <X11/Xutil.h> #include <GL/gl.h> #include <GL/glx.h> #include <CL/cl.h> #include <CL/cl_gl.h> #define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091 #define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092 typedef GLXContext (*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, Bool, const int*); // Helper to check for extension string presence. Adapted from: // http://www.opengl.org/resources/features/OGLextensions/ static bool isExtensionSupported(const char *extList, const char *extension) { const char *start; const char *where, *terminator; /* Extension names should not have spaces. */ where = strchr(extension, ' '); if (where || *extension == '\0') return false; /* It takes a bit of care to be fool-proof about parsing the OpenGL extensions string. Don't be fooled by sub-strings, etc. */ for (start=extList;;) { where = strstr(start, extension); if (!where) break; terminator = where + strlen(extension); if ( where == start || *(where - 1) == ' ' ) if ( *terminator == ' ' || *terminator == '\0' ) return true; start = terminator; } return false; } static bool ctxErrorOccurred = false; static int ctxErrorHandler( Display *dpy, XErrorEvent *ev ) { ctxErrorOccurred = true; return 0; } void test_kernel(cl_mem a_mem_obj, cl_mem b_mem_obj, cl_mem c_mem_obj, cl_kernel kernel, int LIST_SIZE, cl_command_queue command_queue) { int err; err = clSetKernelArg(kernel, 0, sizeof(cl_mem), (void *)&a_mem_obj); printf("err? %d\tset kernel arg 0\n", err); err = clSetKernelArg(kernel, 1, sizeof(cl_mem), (void *)&b_mem_obj); printf("err? %d\n", err); err = clSetKernelArg(kernel, 2, sizeof(cl_mem), (void *)&c_mem_obj); printf("err? %d\n", err); // Execute the OpenCL kernel on the list size_t global_item_size = LIST_SIZE; // Process the entire lists size_t local_item_size = 64; // Divide work items into groups of 64 err = clEnqueueNDRangeKernel(command_queue, kernel, 1, NULL, &global_item_size, &local_item_size, 0, NULL, NULL); printf("err? %d\t(kernel diff)\n", err); // Read the memory buffer C on the device to the local variable C long long *C; C= (long long*)malloc(sizeof(*C)*LIST_SIZE); err = clEnqueueReadBuffer(command_queue, c_mem_obj, CL_TRUE, 0, LIST_SIZE * sizeof(*C), C, 0, NULL, NULL); printf("err? %d(copy result)\n", err); for (int i=0; i<LIST_SIZE && i<10; i++) { printf("%lld\n", C[i]); } free(C); } int main(int argc, char* argv[]) { Display *display = XOpenDisplay(NULL); if (!display) { printf("Failed to open X display\n"); exit(1); } // Get a matching FB config static int visual_attribs[] = { GLX_X_RENDERABLE , True, GLX_DRAWABLE_TYPE , GLX_WINDOW_BIT, GLX_RENDER_TYPE , GLX_RGBA_BIT, GLX_X_VISUAL_TYPE , GLX_TRUE_COLOR, GLX_RED_SIZE , 8, GLX_GREEN_SIZE , 8, GLX_BLUE_SIZE , 8, GLX_ALPHA_SIZE , 8, GLX_DEPTH_SIZE , 24, GLX_STENCIL_SIZE , 8, GLX_DOUBLEBUFFER , True, //GLX_SAMPLE_BUFFERS , 1, //GLX_SAMPLES , 4, None }; int glx_major, glx_minor; // FBConfigs were added in GLX version 1.3. if ( !glXQueryVersion( display, &glx_major, &glx_minor ) || ( ( glx_major == 1 ) && ( glx_minor < 3 ) ) || ( glx_major < 1 ) ) { printf("Invalid GLX version"); exit(1); } printf( "Getting matching framebuffer configs\n" ); int fbcount; GLXFBConfig* fbc = glXChooseFBConfig(display, DefaultScreen(display), visual_attribs, &fbcount); if (!fbc) { printf( "Failed to retrieve a framebuffer config\n" ); exit(1); } printf( "Found %d matching FB configs.\n", fbcount ); // Pick the FB config/visual with the most samples per pixel printf( "Getting XVisualInfos\n" ); int best_fbc = -1, worst_fbc = -1, best_num_samp = -1, worst_num_samp = 999; int i; for (i=0; i<fbcount; ++i) { XVisualInfo *vi = glXGetVisualFromFBConfig( display, fbc[i] ); if ( vi ) { int samp_buf, samples; glXGetFBConfigAttrib( display, fbc[i], GLX_SAMPLE_BUFFERS, &samp_buf ); glXGetFBConfigAttrib( display, fbc[i], GLX_SAMPLES , &samples ); printf( " Matching fbconfig %d, visual ID 0x%2lx: SAMPLE_BUFFERS = %d," " SAMPLES = %d\n", i, vi -> visualid, samp_buf, samples ); if ( best_fbc < 0 || samp_buf && samples > best_num_samp ) best_fbc = i, best_num_samp = samples; if ( worst_fbc < 0 || !samp_buf || samples < worst_num_samp ) worst_fbc = i, worst_num_samp = samples; } XFree( vi ); } GLXFBConfig bestFbc = fbc[ best_fbc ]; // Be sure to free the FBConfig list allocated by glXChooseFBConfig() XFree( fbc ); #if 0 // Get a visual XVisualInfo *vi = glXGetVisualFromFBConfig( display, bestFbc ); printf( "Chosen visual ID = 0x%lx\n", vi->visualid ); printf( "Creating colormap\n" ); XSetWindowAttributes swa; Colormap cmap; swa.colormap = cmap = XCreateColormap( display, RootWindow( display, vi->screen ), vi->visual, AllocNone ); swa.background_pixmap = None ; swa.border_pixel = 0; swa.event_mask = StructureNotifyMask; printf( "Creating window\n" ); Window win = XCreateWindow( display, RootWindow( display, vi->screen ), 0, 0, 100, 100, 0, vi->depth, InputOutput, vi->visual, CWBorderPixel|CWColormap|CWEventMask, &swa ); if ( !win ) { printf( "Failed to create window.\n" ); exit(1); } // Done with the visual info data XFree( vi ); XStoreName( display, win, "GL 3.0 Window" ); printf( "Mapping window\n" ); XMapWindow( display, win ); #endif // Get the default screen's GLX extension list const char *glxExts = glXQueryExtensionsString( display, DefaultScreen( display ) ); // NOTE: It is not necessary to create or make current to a context before // calling glXGetProcAddressARB glXCreateContextAttribsARBProc glXCreateContextAttribsARB = 0; glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc) glXGetProcAddressARB( (const GLubyte *) "glXCreateContextAttribsARB" ); GLXContext ctx = 0; // Install an X error handler so the application won't exit if GL 3.0 // context allocation fails. // // Note this error handler is global. All display connections in all threads // of a process use the same error handler, so be sure to guard against other // threads issuing X commands while this code is running. ctxErrorOccurred = false; int (*oldHandler)(Display*, XErrorEvent*) = XSetErrorHandler(&ctxErrorHandler); // Check for the GLX_ARB_create_context extension string and the function. // If either is not present, use GLX 1.3 context creation method. if ( !isExtensionSupported( glxExts, "GLX_ARB_create_context" ) || !glXCreateContextAttribsARB ) { printf( "glXCreateContextAttribsARB() not found" " ... using old-style GLX context\n" ); ctx = glXCreateNewContext( display, bestFbc, GLX_RGBA_TYPE, 0, True ); } // If it does, try to get a GL 3.0 context! else { int context_attribs[] = { GLX_CONTEXT_MAJOR_VERSION_ARB, 3, GLX_CONTEXT_MINOR_VERSION_ARB, 0, //GLX_CONTEXT_FLAGS_ARB , GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB, None }; printf( "Creating context\n" ); ctx = glXCreateContextAttribsARB( display, bestFbc, 0, True, context_attribs ); // Sync to ensure any errors generated are processed. XSync( display, False ); if ( !ctxErrorOccurred && ctx ) printf( "Created GL 3.0 context\n" ); else { // Couldn't create GL 3.0 context. Fall back to old-style 2.x context. // When a context version below 3.0 is requested, implementations will // return the newest context version compatible with OpenGL versions less // than version 3.0. // GLX_CONTEXT_MAJOR_VERSION_ARB = 1 context_attribs[1] = 1; // GLX_CONTEXT_MINOR_VERSION_ARB = 0 context_attribs[3] = 0; ctxErrorOccurred = false; printf( "Failed to create GL 3.0 context" " ... using old-style GLX context\n" ); ctx = glXCreateContextAttribsARB( display, bestFbc, 0, True, context_attribs ); } } // Sync to ensure any errors generated are processed. XSync( display, False ); // Restore the original error handler XSetErrorHandler( oldHandler ); if ( ctxErrorOccurred || !ctx ) { printf( "Failed to create an OpenGL context\n" ); exit(1); } // Verifying that context is a direct context if ( ! glXIsDirect ( display, ctx ) ) { printf( "Indirect GLX rendering context obtained\n" ); } else { printf( "Direct GLX rendering context obtained\n" ); } printf( "Making context current\n" ); glXMakeCurrent( display, 0, ctx ); #define IMAGE_DIAM 512 #define LIST_SIZE (IMAGE_DIAM*IMAGE_DIAM*3) GLuint texture_id; { glGenTextures(1, &texture_id); printf("err? %d\n", glGetError()); glBindTexture(GL_TEXTURE_2D, texture_id); printf("err? %d\t(bind texture)\n", glGetError()); unsigned char random_stack_crap[LIST_SIZE]; glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, IMAGE_DIAM, IMAGE_DIAM, 0, GL_RGB, GL_UNSIGNED_BYTE, random_stack_crap); printf("err? %d\n", glGetError()); } // // // cl_platform_id platform; clGetPlatformIDs(1, &platform, NULL); cl_device_id device; clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, 1, &device, NULL); printf("device\t%p\n", device); printf ("context\t%p\t%p\n", ctx, glXGetCurrentContext()); printf ("display\t%p\t%p\n", display, glXGetCurrentDisplay()); cl_context_properties props[] = { CL_GL_CONTEXT_KHR, (cl_context_properties) glXGetCurrentContext(), CL_GLX_DISPLAY_KHR, (cl_context_properties) glXGetCurrentDisplay(), CL_CONTEXT_PLATFORM, (cl_context_properties) platform, 0 }; int err=0; cl_context cl = clCreateContext(props, 1, &device, NULL, NULL, &err); printf("err? %d\n", err); printf("cl context %p\n", cl); // // https://www.eriksmistad.no/getting-started-with-opencl-and-gpu-computing/ // cl_command_queue command_queue = clCreateCommandQueue(cl, device, 0, &err); printf("err? %d\n", err); printf("cl queue %p\n", command_queue); // Create memory buffers on the device for each vector cl_mem z_mem_obj = clCreateFromGLTexture( cl, CL_MEM_READ_WRITE, GL_TEXTURE_2D, 0, texture_id, &err); cl_mem a_mem_obj = clCreateBuffer(cl, CL_MEM_READ_ONLY, LIST_SIZE , NULL, &err); printf("err? %d\n", err); cl_mem b_mem_obj = clCreateBuffer(cl, CL_MEM_READ_ONLY, LIST_SIZE , NULL, &err); printf("err? %d\n", err); cl_mem c_mem_obj = clCreateBuffer(cl, CL_MEM_WRITE_ONLY, LIST_SIZE*8 , NULL, &err); printf("err? %d\n", err); // Copy the lists A and B to their respective memory buffers { unsigned char *A = (unsigned char*) malloc(LIST_SIZE); for (int i=0; i<LIST_SIZE; i++) { A[i] = i+2; } unsigned char *B = (unsigned char*) malloc(LIST_SIZE); for (int i=0; i<LIST_SIZE; i++) { B[i] = 2*i; } err = clEnqueueWriteBuffer(command_queue, a_mem_obj, CL_TRUE, 0, LIST_SIZE, A, 0, NULL, NULL); printf("err? %d\tcopy A\n", err); err = clEnqueueWriteBuffer(command_queue, b_mem_obj, CL_TRUE, 0, LIST_SIZE, B, 0, NULL, NULL); printf("err? %d\tcopy B\n", err); } const char* source_str = "__kernel void diff(__global uchar* rgb_a, __global uchar* rgb_b, __global ulong * diff_out)\n\ {\n\ int idx = get_global_id(0);\n\ diff_out[idx] = abs((int)rgb_a[idx] - (int)rgb_b[idx]);\n\ }"; size_t source_size = strlen(source_str); // Create a program from the kernel source cl_program program = clCreateProgramWithSource(cl, 1, (const char **)&source_str, (const size_t *)&source_size, &err); printf("err? %d\t(create program)\n", err); // Build the program err = clBuildProgram(program, 1, &device, NULL, NULL, NULL); printf("err? %d\n", err); // Create the OpenCL kernel cl_kernel kernel = clCreateKernel(program, "diff", &err); printf("err? %d\n", err); err = clSetKernelArg(kernel, 0, sizeof(cl_mem), (void *)&a_mem_obj); printf("err? %d\n", err); err = clSetKernelArg(kernel, 1, sizeof(cl_mem), (void *)&b_mem_obj); printf("err? %d\n", err); err = clSetKernelArg(kernel, 2, sizeof(cl_mem), (void *)&c_mem_obj); printf("err? %d\n", err); // Execute the OpenCL kernel on the list size_t global_item_size = LIST_SIZE; // Process the entire lists size_t local_item_size = 64; // Divide work items into groups of 64 err = clEnqueueNDRangeKernel(command_queue, kernel, 1, NULL, &global_item_size, &local_item_size, 0, NULL, NULL); printf("err? %d\t(kernel diff)\n", err); // Read the memory buffer C on the device to the local variable C long long *C; C= (long long*)malloc(sizeof(*C)*LIST_SIZE); err = clEnqueueReadBuffer(command_queue, c_mem_obj, CL_TRUE, 0, LIST_SIZE * sizeof(*C), C, 0, NULL, NULL); printf("err? %d(copy resul)\n", err); for (int i=0; i<LIST_SIZE && i<10; i++) { printf("%lld\n", C[i]); } free(C); test_kernel(a_mem_obj, b_mem_obj, c_mem_obj, kernel, LIST_SIZE, command_queue); test_kernel(z_mem_obj, b_mem_obj, c_mem_obj, kernel, LIST_SIZE, command_queue); return 0; } The output on my linux/gentoo box with mesa-progs-8.4.0 is Getting matching framebuffer configs Found 10 matching FB configs. Getting XVisualInfos Matching fbconfig 0, visual ID 0x24: SAMPLE_BUFFERS = 0, SAMPLES = 0 Matching fbconfig 1, visual ID 0x7a: SAMPLE_BUFFERS = 0, SAMPLES = 0 Matching fbconfig 2, visual ID 0x38: SAMPLE_BUFFERS = 1, SAMPLES = 2 Matching fbconfig 3, visual ID 0x8e: SAMPLE_BUFFERS = 1, SAMPLES = 2 Matching fbconfig 4, visual ID 0x3a: SAMPLE_BUFFERS = 1, SAMPLES = 4 Matching fbconfig 5, visual ID 0x90: SAMPLE_BUFFERS = 1, SAMPLES = 4 Matching fbconfig 6, visual ID 0x44: SAMPLE_BUFFERS = 1, SAMPLES = 8 Matching fbconfig 7, visual ID 0x9a: SAMPLE_BUFFERS = 1, SAMPLES = 8 Matching fbconfig 8, visual ID 0x4c: SAMPLE_BUFFERS = 1, SAMPLES = 16 Matching fbconfig 9, visual ID 0xa2: SAMPLE_BUFFERS = 1, SAMPLES = 16 Creating context Created GL 3.0 context Direct GLX rendering context obtained Making context current err? 0 err? 0 (bind texture) err? 0 device 0x557c1755cef0 context 0x557c173e0b68 0x557c173e0b68 display 0x557c172ee950 0x557c172ee950 err? 0 cl context 0x557c17559340 err? 0 cl queue 0x557c177dd080 err? 0 err? 0 err? 0 err? 0 copy A err? 0 copy B err? 0 (create program) err? 0 err? 0 err? 0 err? 0 err? 0 err? 0 (kernel diff) err? 0(copy resul) 2 1 0 1 2 3 4 5 6 7 err? 0 set kernel arg 0 err? 0 err? 0 err? 0 (kernel diff) err? 0(copy result) 2 1 0 1 2 3 4 5 6 7 err? -38 set kernel arg 0 err? 0 err? 0 err? 0 (kernel diff) err? 0(copy result) 2 1 0 1 2 3 4 5 6 7 Notice the err? -38 set kernel arg 0 which corresponds to the final test where I pass z_mem_obj to use the buffer converted from a GL texture. clinfo | grep khr lists cl_khr_gl_sharing in the Platform Extensions and Device Extensions.
nvidia opengl framebuffer object forces vsync on
Basically I implemented gamma correction into a q3 based game to get rid of the annoying SetDeviceGammaRamp. I'm using GL_EXT_framebuffer_object for a post process vertex shader. It works pretty fine except that it has some weird behavior on nvidia gpus: It forces vsync to be enabled except when it is explicitly disabled in the control panel. If I use the standard control panel's settings and the framebuffer is enabled vsync is forced, but if I remove the framebuffer it goes back to normal behavior. wglSwapIntervalEXT does nothing I tested it on an nvidia mobile GPU, someone could reproduce it on a desktop GPU I also tested an integrated intel gpu and two different amd gpu's and all of them didn't have the issue. initialization: (unrelevant i guess) // ouned: gamma correction const char *g_GammaVertexShaderARB = { "void main(void)" "\n" "{" "\n" "gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;" "\n" "gl_TexCoord[0] = gl_MultiTexCoord0;" "\n" "}" }; const char *g_GammaFragmentShaderARB = { "uniform sampler2D sceneBuffer;" "\n" "uniform float gamma;" "\n" "\n" "void main(void)" "\n" "{" "\n" "vec2 uv = gl_TexCoord[0].xy;" "\n" "vec3 color = texture2D(sceneBuffer, uv).rgb;" "\n" "if (uv.x<0.50)" "\n" "gl_FragColor.rgb = pow(color, vec3(1.0 / 1.5));" "\n" "else" "\n" "gl_FragColor.rgb = color;" "\n" "gl_FragColor.a = 1.0;" "\n" "}" }; tr.m_hVShader = qglCreateShaderObjectARB(GL_VERTEX_SHADER_ARB); qglShaderSourceARB(tr.m_hVShader, 1, (const GLcharARB **)&g_GammaVertexShaderARB, NULL); qglCompileShaderARB(tr.m_hVShader); if (qglGetError() != GL_NO_ERROR) { ri.Printf(PRINT_ERROR, "Failed compiling gamma vertrex shader\n"); } tr.m_hFShader = qglCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB); qglShaderSourceARB(tr.m_hFShader, 1, (const GLcharARB **)&g_GammaFragmentShaderARB, NULL); qglCompileShaderARB(tr.m_hFShader); if (qglGetError() != GL_NO_ERROR) { ri.Printf(PRINT_ERROR, "Failed compiling gamma fragment shader\n"); } tr.gammaProgram = qglCreateProgramObjectARB(); qglAttachObjectARB(tr.gammaProgram, tr.m_hVShader); qglAttachObjectARB(tr.gammaProgram, tr.m_hFShader); qglLinkProgramARB(tr.gammaProgram); if (qglGetError() != GL_NO_ERROR) { ri.Printf(PRINT_ERROR, "Failed linking shaders\n"); } qglUseProgramObjectARB(tr.gammaProgram); tr.gammaUniformLoc = qglGetUniformLocationARB(tr.gammaProgram, "gamma"); tr.gammaSceneBufferLoc = qglGetUniformLocationARB(tr.gammaProgram, "sceneBuffer"); qglValidateProgramARB(tr.gammaProgram); qglUseProgramObjectARB(0); // framebuffer object tr.gammaFramebuffer = 0; qglGenFramebuffersEXT(1, &tr.gammaFramebuffer); qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, tr.gammaFramebuffer); // depth buffer tr.gammaRenderDepthBuffer = 0; qglGenRenderbuffersEXT(1, &tr.gammaRenderDepthBuffer); qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, tr.gammaRenderDepthBuffer); qglRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, glConfig.vidWidth, glConfig.vidHeight); tr.gammaRenderTarget = 0; qglGenTextures(1, &tr.gammaRenderTarget); qglBindTexture(GL_TEXTURE_2D, tr.gammaRenderTarget); qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, glConfig.vidWidth, glConfig.vidHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); qglGenerateMipmapEXT(GL_TEXTURE_2D); qglBindTexture(GL_TEXTURE_2D, 0); qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, tr.gammaRenderTarget, 0); qglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, tr.gammaRenderDepthBuffer); qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); On the beginning of a frame: qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, tr.gammaFramebuffer); qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, tr.gammaRenderDepthBuffer); qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); on the end of a frame: qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); if (!backEnd.projection2D) { qglViewport(0, 0, glConfig.vidWidth, glConfig.vidHeight); qglScissor(0, 0, glConfig.vidWidth, glConfig.vidHeight); qglMatrixMode(GL_PROJECTION); qglLoadIdentity(); qglOrtho(0, glConfig.vidWidth, glConfig.vidHeight, 0, 0, 1); qglMatrixMode(GL_MODELVIEW); qglLoadIdentity(); GL_State(GLS_DEPTHTEST_DISABLE); } qglUseProgramObjectARB(tr.gammaProgram); qglEnable(GL_TEXTURE_2D); qglUniform1iARB(tr.gammaSceneBufferLoc, 0); qglColor3f(tr.identityLight, tr.identityLight, tr.identityLight); qglActiveTextureARB(GL_TEXTURE0); qglBindTexture(GL_TEXTURE_2D, tr.gammaRenderTarget); qglBegin(GL_QUADS); qglTexCoord2f(0, 1); qglVertex2f(0, 0); qglTexCoord2f(1, 1); qglVertex2f(glConfig.vidWidth, 0); qglTexCoord2f(1, 0); qglVertex2f(glConfig.vidWidth, glConfig.vidHeight); qglTexCoord2f(0, 0); qglVertex2f(0, glConfig.vidHeight); qglEnd(); qglUseProgramObjectARB(0); So, what else can cause vsync to be enabled?
losing capabilities after setuid()
Trying to set cap_setgid,cap_setuid,cap_setpcap. #include <sys/types.h> #include <sys/capability.h> int main() { cap_t caps; caps = cap_get_proc(); cap_value_t cap_list[2]; cap_list[0] = CAP_SETUID; cap_list[1] = CAP_SETGID; cap_set_flag(caps, CAP_EFFECTIVE, 2, cap_list, CAP_SET); cap_set_flag(caps, CAP_INHERITABLE, 2, cap_list, CAP_SET); cap_set_proc(caps); cap_free(caps); setgid(65534); setuid(65534); cap_get_proc(); setgid(0); setuid(0); return 0; } Execution is going under root user. Tracing the program shows this capget({_LINUX_CAPABILITY_VERSION_3, 0}, NULL) = 0 capget({_LINUX_CAPABILITY_VERSION_3, 0}, {CAP_CHOWN|CAP_DAC_OVERRIDE|CAP_DAC_READ_SEARCH|CAP_FOWNER|CAP_FSETID|CAP_KILL|CAP_SETGID|CAP_SETUID|CAP_SETPCAP|CAP_LINUX_IMMUTABLE|CAP_NET_BIND_SERVICE|CAP_NET_BROADCAST|CAP_NET_ADMIN|CAP_NET_RAW|CAP_IPC_LOCK|CAP_IPC_OWNER|CAP_SYS_MODULE|CAP_SYS_RAWIO|CAP_SYS_CHROOT|CAP_SYS_PTRACE|CAP_SYS_PACCT|CAP_SYS_ADMIN|CAP_SYS_BOOT|CAP_SYS_NICE|CAP_SYS_RESOURCE|CAP_SYS_TIME|CAP_SYS_TTY_CONFIG|CAP_MKNOD|CAP_LEASE|CAP_AUDIT_WRITE|CAP_AUDIT_CONTROL|CAP_SETFCAP, CAP_CHOWN|CAP_DAC_OVERRIDE|CAP_DAC_READ_SEARCH|CAP_FOWNER|CAP_FSETID|CAP_KILL|CAP_SETGID|CAP_SETUID|CAP_SETPCAP|CAP_LINUX_IMMUTABLE|CAP_NET_BIND_SERVICE|CAP_NET_BROADCAST|CAP_NET_ADMIN|CAP_NET_RAW|CAP_IPC_LOCK|CAP_IPC_OWNER|CAP_SYS_MODULE|CAP_SYS_RAWIO|CAP_SYS_CHROOT|CAP_SYS_PTRACE|CAP_SYS_PACCT|CAP_SYS_ADMIN|CAP_SYS_BOOT|CAP_SYS_NICE|CAP_SYS_RESOURCE|CAP_SYS_TIME|CAP_SYS_TTY_CONFIG|CAP_MKNOD|CAP_LEASE|CAP_AUDIT_WRITE|CAP_AUDIT_CONTROL|CAP_SETFCAP, 0}) = 0 capset({_LINUX_CAPABILITY_VERSION_3, 0}, {CAP_CHOWN|CAP_DAC_OVERRIDE|CAP_DAC_READ_SEARCH|CAP_FOWNER|CAP_FSETID|CAP_KILL|CAP_SETGID|CAP_SETUID|CAP_SETPCAP|CAP_LINUX_IMMUTABLE|CAP_NET_BIND_SERVICE|CAP_NET_BROADCAST|CAP_NET_ADMIN|CAP_NET_RAW|CAP_IPC_LOCK|CAP_IPC_OWNER|CAP_SYS_MODULE|CAP_SYS_RAWIO|CAP_SYS_CHROOT|CAP_SYS_PTRACE|CAP_SYS_PACCT|CAP_SYS_ADMIN|CAP_SYS_BOOT|CAP_SYS_NICE|CAP_SYS_RESOURCE|CAP_SYS_TIME|CAP_SYS_TTY_CONFIG|CAP_MKNOD|CAP_LEASE|CAP_AUDIT_WRITE|CAP_AUDIT_CONTROL|CAP_SETFCAP, CAP_CHOWN|CAP_DAC_OVERRIDE|CAP_DAC_READ_SEARCH|CAP_FOWNER|CAP_FSETID|CAP_KILL|CAP_SETGID|CAP_SETUID|CAP_SETPCAP|CAP_LINUX_IMMUTABLE|CAP_NET_BIND_SERVICE|CAP_NET_BROADCAST|CAP_NET_ADMIN|CAP_NET_RAW|CAP_IPC_LOCK|CAP_IPC_OWNER|CAP_SYS_MODULE|CAP_SYS_RAWIO|CAP_SYS_CHROOT|CAP_SYS_PTRACE|CAP_SYS_PACCT|CAP_SYS_ADMIN|CAP_SYS_BOOT|CAP_SYS_NICE|CAP_SYS_RESOURCE|CAP_SYS_TIME|CAP_SYS_TTY_CONFIG|CAP_MKNOD|CAP_LEASE|CAP_AUDIT_WRITE|CAP_AUDIT_CONTROL|CAP_SETFCAP, CAP_SETGID|CAP_SETUID|CAP_SETPCAP}) = 0 setgid(65534) = 0 setuid(65534) = 0 capget({_LINUX_CAPABILITY_VERSION_3, 0}, NULL) = 0 capget({_LINUX_CAPABILITY_VERSION_3, 0}, {0, 0, CAP_SETGID|CAP_SETUID|CAP_SETPCAP}) = 0 setgid(0) = -1 EPERM (Operation not permitted) setuid(0) = -1 EPERM (Operation not permitted) exit_group(0) = ? +++ exited with 0 +++ Privileges are set but do not work. Any suggestions how to solve this problem? UPDATE: prctl added to code 21a22 > prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0); 24a26 > cap_set_flag(caps, CAP_EFFECTIVE, 3, cap_list, CAP_SET); so now it is prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0); setgid(65534); setuid(65534); cap_set_flag(caps, CAP_EFFECTIVE, 3, cap_list, CAP_SET); Caps were inherited after setuid, and caps that were set manually are still there, but it didn't solve the problem setgid(65534) = 0 setuid(65534) = 0 capget({_LINUX_CAPABILITY_VERSION_3, 0}, NULL) = 0 capget({_LINUX_CAPABILITY_VERSION_3, 0}, {0, CAP_CHOWN|CAP_DAC_OVERRIDE|CAP_DAC_READ_SEARCH|CAP_FOWNER|CAP_FSETID|CAP_KILL|CAP_SETGID|CAP_SETUID|CAP_SETPCAP|CAP_LINUX_IMMUTABLE|CAP_NET_BIND_SERVICE|CAP_NET_BROADCAST|CAP_NET_ADMIN|CAP_NET_RAW|CAP_IPC_LOCK|CAP_IPC_OWNER|CAP_SYS_MODULE|CAP_SYS_RAWIO|CAP_SYS_CHROOT|CAP_SYS_PTRACE|CAP_SYS_PACCT|CAP_SYS_ADMIN|CAP_SYS_BOOT|CAP_SYS_NICE|CAP_SYS_RESOURCE|CAP_SYS_TIME|CAP_SYS_TTY_CONFIG|CAP_MKNOD|CAP_LEASE|CAP_AUDIT_WRITE|CAP_AUDIT_CONTROL|CAP_SETFCAP, CAP_SETGID|CAP_SETUID|CAP_SETPCAP}) = 0 setgid(0) = -1 EPERM (Operation not permitted) setuid(0) = -1 EPERM (Operation not permitted) exit_group(0) = ? +++ exited with 0 +++ UPDATE2: Can't understand it. Ive added 2strs after 1st setuid, to check out for caps. printf("cape set %d\n", cap_set_flag(caps, CAP_EFFECTIVE, 3, cap_list, CAP_SET)); printf("%s\n", cap_to_text(cap_get_proc(), NULL)); it returned catp set 0 =p cap_setgid,cap_setuid,cap_setpcap+i Effective flag is not set, but cap_set_flag returned 0
By default, capability sets are lost across an UID transition; use prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0); to retain permitted capabilities (cap_set_flag(caps, CAP_PERMITTED, ...)). Note that the effective capability set will be reset, but can be re-established. The following works fine for me. #include <sys/capability.h> #include <sys/prctl.h> #include <unistd.h> int main(int argc, char **argv) { cap_value_t cap_values[] = {CAP_SETUID, CAP_SETGID}; cap_t caps; caps = cap_get_proc(); cap_set_flag(caps, CAP_PERMITTED, 2, cap_values, CAP_SET); cap_set_proc(caps); prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0); cap_free(caps); setgid(65534); setuid(65534); caps = cap_get_proc(); cap_set_flag(caps, CAP_EFFECTIVE, 2, cap_values, CAP_SET); cap_set_proc(caps); cap_free(caps); setgid(0); setuid(0); return 0; } $ sudo strace ./a.out ... capget({_LINUX_CAPABILITY_VERSION_3, 0}, {CAP_CHOWN|CAP_DAC_OVERRIDE|CAP_DAC_READ_SEARCH|CAP_FOWNER|CAP_FSETID|CAP_KILL|CAP_SETGID|CAP_SETUID|CAP_SETPCAP|CAP_LINUX_IMMUTABLE|CAP_NET_BIND_SERVICE|CAP_NET_BROADCAST|CAP_NET_ADMIN|CAP_NET_RAW|CAP_IPC_LOCK|CAP_IPC_OWNER|CAP_SYS_MODULE|CAP_SYS_RAWIO|CAP_SYS_CHROOT|CAP_SYS_PTRACE|CAP_SYS_PACCT|CAP_SYS_ADMIN|CAP_SYS_BOOT|CAP_SYS_NICE|CAP_SYS_RESOURCE|CAP_SYS_TIME|CAP_SYS_TTY_CONFIG|CAP_MKNOD|CAP_LEASE|CAP_AUDIT_WRITE|CAP_AUDIT_CONTROL|CAP_SETFCAP, CAP_CHOWN|CAP_DAC_OVERRIDE|CAP_DAC_READ_SEARCH|CAP_FOWNER|CAP_FSETID|CAP_KILL|CAP_SETGID|CAP_SETUID|CAP_SETPCAP|CAP_LINUX_IMMUTABLE|CAP_NET_BIND_SERVICE|CAP_NET_BROADCAST|CAP_NET_ADMIN|CAP_NET_RAW|CAP_IPC_LOCK|CAP_IPC_OWNER|CAP_SYS_MODULE|CAP_SYS_RAWIO|CAP_SYS_CHROOT|CAP_SYS_PTRACE|CAP_SYS_PACCT|CAP_SYS_ADMIN|CAP_SYS_BOOT|CAP_SYS_NICE|CAP_SYS_RESOURCE|CAP_SYS_TIME|CAP_SYS_TTY_CONFIG|CAP_MKNOD|CAP_LEASE|CAP_AUDIT_WRITE|CAP_AUDIT_CONTROL|CAP_SETFCAP, 0}) = 0 capset({_LINUX_CAPABILITY_VERSION_3, 0}, {CAP_CHOWN|CAP_DAC_OVERRIDE|CAP_DAC_READ_SEARCH|CAP_FOWNER|CAP_FSETID|CAP_KILL|CAP_SETGID|CAP_SETUID|CAP_SETPCAP|CAP_LINUX_IMMUTABLE|CAP_NET_BIND_SERVICE|CAP_NET_BROADCAST|CAP_NET_ADMIN|CAP_NET_RAW|CAP_IPC_LOCK|CAP_IPC_OWNER|CAP_SYS_MODULE|CAP_SYS_RAWIO|CAP_SYS_CHROOT|CAP_SYS_PTRACE|CAP_SYS_PACCT|CAP_SYS_ADMIN|CAP_SYS_BOOT|CAP_SYS_NICE|CAP_SYS_RESOURCE|CAP_SYS_TIME|CAP_SYS_TTY_CONFIG|CAP_MKNOD|CAP_LEASE|CAP_AUDIT_WRITE|CAP_AUDIT_CONTROL|CAP_SETFCAP, CAP_CHOWN|CAP_DAC_OVERRIDE|CAP_DAC_READ_SEARCH|CAP_FOWNER|CAP_FSETID|CAP_KILL|CAP_SETGID|CAP_SETUID|CAP_SETPCAP|CAP_LINUX_IMMUTABLE|CAP_NET_BIND_SERVICE|CAP_NET_BROADCAST|CAP_NET_ADMIN|CAP_NET_RAW|CAP_IPC_LOCK|CAP_IPC_OWNER|CAP_SYS_MODULE|CAP_SYS_RAWIO|CAP_SYS_CHROOT|CAP_SYS_PTRACE|CAP_SYS_PACCT|CAP_SYS_ADMIN|CAP_SYS_BOOT|CAP_SYS_NICE|CAP_SYS_RESOURCE|CAP_SYS_TIME|CAP_SYS_TTY_CONFIG|CAP_MKNOD|CAP_LEASE|CAP_AUDIT_WRITE|CAP_AUDIT_CONTROL|CAP_SETFCAP, 0}) = 0 prctl(PR_SET_KEEPCAPS, 1) = 0 setgid(65534) = 0 setuid(65534) = 0 capget({_LINUX_CAPABILITY_VERSION_3, 0}, NULL) = 0 capget({_LINUX_CAPABILITY_VERSION_3, 0}, {0, CAP_CHOWN|CAP_DAC_OVERRIDE|CAP_DAC_READ_SEARCH|CAP_FOWNER|CAP_FSETID|CAP_KILL|CAP_SETGID|CAP_SETUID|CAP_SETPCAP|CAP_LINUX_IMMUTABLE|CAP_NET_BIND_SERVICE|CAP_NET_BROADCAST|CAP_NET_ADMIN|CAP_NET_RAW|CAP_IPC_LOCK|CAP_IPC_OWNER|CAP_SYS_MODULE|CAP_SYS_RAWIO|CAP_SYS_CHROOT|CAP_SYS_PTRACE|CAP_SYS_PACCT|CAP_SYS_ADMIN|CAP_SYS_BOOT|CAP_SYS_NICE|CAP_SYS_RESOURCE|CAP_SYS_TIME|CAP_SYS_TTY_CONFIG|CAP_MKNOD|CAP_LEASE|CAP_AUDIT_WRITE|CAP_AUDIT_CONTROL|CAP_SETFCAP, 0}) = 0 capset({_LINUX_CAPABILITY_VERSION_3, 0}, {CAP_SETGID|CAP_SETUID, CAP_CHOWN|CAP_DAC_OVERRIDE|CAP_DAC_READ_SEARCH|CAP_FOWNER|CAP_FSETID|CAP_KILL|CAP_SETGID|CAP_SETUID|CAP_SETPCAP|CAP_LINUX_IMMUTABLE|CAP_NET_BIND_SERVICE|CAP_NET_BROADCAST|CAP_NET_ADMIN|CAP_NET_RAW|CAP_IPC_LOCK|CAP_IPC_OWNER|CAP_SYS_MODULE|CAP_SYS_RAWIO|CAP_SYS_CHROOT|CAP_SYS_PTRACE|CAP_SYS_PACCT|CAP_SYS_ADMIN|CAP_SYS_BOOT|CAP_SYS_NICE|CAP_SYS_RESOURCE|CAP_SYS_TIME|CAP_SYS_TTY_CONFIG|CAP_MKNOD|CAP_LEASE|CAP_AUDIT_WRITE|CAP_AUDIT_CONTROL|CAP_SETFCAP, 0}) = 0 setgid(0) = 0 setuid(0) = 0 ...
I think you confused CAP_PERMITTED set with CAP_INHERITABLE, Unless you are using threads/exec , you want to use CAP_PERMITTED. Inheritable (formerly known as allowed): This set is ANDed with the thread's inheritable set to determine which inheritable capabilities are enabled in the permitted set of the thread after the execve(2) As for update2: try printing out cap_to_text(cap_get_proc()) before/after and also consider what is the difference between cap_set_flag and cap_set_proc.