Valgrind’s “Syscall param semctl(arg) points to uninitialised byte(s)”

Saw some interesting behavior with Valgrind that finally became clear after some digging.

I’m using:

val = semctl(semid, 0, GETVAL)

after getting the semaphore id from a shared memory segment set up by another process. It works as expected, but valgrind reports:

==332== Syscall param semctl(arg) points to uninitialised byte(s)
==332==    at 0xB5DE0E: semctl@@GLIBC_2.2 (in /lib/libc-2.5.so)
==332==    by 0x8048620: main (testClient.c:21)

You can see yourself with testServer.c & testClient.c. Run testServer to set up the shared mem & semaphore, then run testClient under valgrind to see the error.

So what’s going on here? semctl takes varargs, with things like SETVAL using a 4th argument like semctl(semid, 0, SETVAL, arg). Something internal must be expanding our semctl call to the 4-arg version, passing in a completely unnecessary (but technically undefined) 4th argument.

Easy solution is to manually specify the 4th arg that we don’t need in semctl:

val = semctl(semid, 0, GETVAL, NULL);

Note that this is NOT an issue if you issue a 4 parameter semctl call anytime before the 3arg version we were having problems with. It’s only when the first semctl your thread makes doesn’t include a 4th arg that the alarm bells trigger.

This is why we use testServer to see ths issue. If we use the 3arg GETVAL semctl in testServer after setting up the semaphore, valgrind wouldn’t complain, as we used the 4arg version to SETVAL.