揮発性のメモ2

知識をメモ書きしておく

sem_openで、Permission denied になる

セマフォを使ってロックをするプログラム

#include <fcntl.h>      // O_CREAT
#include <semaphore.h>  // sem_wait
#include <stdio.h>      // printf
#include <unistd.h>     // sleep

int main()
{
    sem_t *sem = sem_open("/unko", O_CREAT, 0666, 1); // ★パーミッション全開のつもり
    if(sem==NULL){
        perror("sem_open");
        return 1;
    }

    printf("ロック\n");
    sem_wait(sem);

    printf("30秒スリープ\n");
    sleep(30);

    printf("アンロック\n");
    sem_post(sem);

    return 0;
}


これを、異なるユーザで起動すると もう片方ではエラーになる。
root権限で起動中に一般権限で起動した例

★root権限側
# ./a.out
ロック
30秒スリープ

★一般権限側
$ ./a.out
sem_open: Permission denied


なぜかというと、sem_openでのパーミッション設定も、umask に引っ張られてしまうため
umask が 0022 の場合はマスクされてしまい、 0666 にしようとしても 0644 になってしまう。

$ umask
0022
$ ls -l /dev/shm/sem.unko
-rw-r--r-- 1 root root 32  4月 11 11:35 /dev/shm/sem.unko

最初にroot権限でセマフォファイルが作られると一般権限ではreadonlyになるので sem_openで失敗してしまう

よって、umask(0) など必要に応じてマスク狩りをする

#include <fcntl.h>      // O_CREAT
#include <semaphore.h>  // sem_wait
#include <stdio.h>      // printf
#include <unistd.h>     // sleep
#include <sys/stat.h>   // umask

int main()
{
    umask(0); // ★★マスク狩り
    sem_t *sem = sem_open("/unko", O_CREAT, 0666, 1); // ★パーミッション全開
    if(sem==NULL){
        perror("sem_open");
        return 1;
    }

    printf("ロック\n");
    sem_wait(sem);

    printf("30秒スリープ\n");
    sleep(30);

    printf("アンロック\n");
    sem_post(sem);

    return 0;
}