Reputation: 327
I am trying to initiate a UNIX semaphore so that I can use it to control two processes.
I copied the sem_init
function from this example. I removed the pshared
parameter because it was not used in the function and corrected int * sem
to int * semid
assuming this was a mistake.
#include <iostream>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <stdio.h>
#include <errno.h>
/* The semaphore key is an arbitrary long integer which serves as an
external identifier by which the semaphore is known to any program
that wishes to use it. */
using namespace std;
#define KEY (1492)
int sem_init(int* semid, unsigned int value) {
/* get the semaphore */
*semid = semget(KEY, 1, IPC_CREAT);
if (*semid == -1) {
printf("Unable to obtain semaphore.\n");
return -1;
}
int ret = semctl( *semid, 0, SETVAL, value);
if (ret == -1) {
printf("Unable to set semaphore value: %s\n", strerror(errno));
return -1;
}
return ret;
}
int main(void) {
int* semid = (int*) malloc(sizeof(int));
sem_init(semid, 1);
return 0;
}
The program prints Unable to set semaphore value: permission denied
. I also copied the first main function from this example and it prints Cannot set semaphore value
.
One thing I should mention is that there does seem to be processes running in the background from previous times that I have run the program, but it won't let me terminate them (it says operation not permitted), so maybe the semaphore is already initialized and it won't let me reinitialize it?
Also another thing. The first example passes IPC_CREAT | IPC_EXCL | 0666
to sem_get
, but when I do this semget
returns -1. It only works if just IPC_CREAT
is passed.
If you could let me know what the 0666
does that would be great because none of the examples explain it.
Upvotes: 0
Views: 1080
Reputation: 180201
The program prints
Unable to set semaphore value: permission denied
.
That would be because in the event that the semget()
call you present in fact creates a new semaphore set, it creates it with no access permissions for anyone. You probably want something more like this:
*semid = semget(KEY, 1, IPC_CREAT | S_IRUSR | S_IWUSR);
That will assign mode 0600; add more permissions as needed. The S_
macros are documented with the open()
function.
One thing I should mention is that there does seem to be processes running in the background from previous times that I have run the program, but it won't let me terminate them (it says operation not permitted), so maybe the semaphore is already initialized and it won't let me reinitialize it?
I don't see any reason why the particular program you presented would continue running in the background, but any semaphore set it creates has kernel persistence: it lives until explicitly removed, which will be past your particular program's termination. You should be able to use the ipcs
command to get a list of current semaphores, and the ipcrm
command to remove old ones. These may require root privilege.
The first example passes
IPC_CREAT | IPC_EXCL | 0666
tosem_get
, but when I do this semget returns -1. It only works if justIPC_CREAT
is passed.
This is again the issue that your semaphore set outlives the program. When you specify IPC_EXCL
, you are explicitly requesting that the call fail (returning -1) if a semaphore set with the specified key already exists, and therefore is not created fresh by the call. It should not be harmful to include the mode bits (the 0666
) when omitting IPC_EXCL
, but they have effect only when a new semaphore set is created. The S_IRUSR
and S_IWUSR
constants I referenced above represent two of the specific mode bits, and in general I recommend using the constants over encoding the mode numerically.
As an aside, note that the ftok()
function is the conventional means to obtain a key value with which to identify a semaphore set.
Upvotes: 2
Reputation: 1
The problems with
*semid = semget(KEY, 1, IPC_CREAT | IPC_EXCL | 0666);
and
int ret = semctl( *semid, 0, SETVAL, value);
are almost certainly caused because the Sys V semaphore identified by *semid
already exists with incorrect permissions, likely because an earlier creation left off the 0666
permissions. Since the semaphore id already exists, you can't attach to it with the IPC_EXCL
flag set.
Assuming you're running on Linux, the ipcs -s
command will show you the existing Sys V semaphores. You can then use the ipcrm
command to remove the semaphore(s) with incorrect permissions and start over.
Upvotes: 2