前提:Waylandはコンポジタ(server)とクライアントのIPCにUNIXソケットを使っている。たいてい $XDG_RUNTIME_DIR/wayland-%d がそう
Server
wayland-server.c
const char* wl_display_add_socket_auto(wl_display*)
snprintf()を使って、ソケットの表示名をwayland-%d(0から開始)という形式で取得wl_socket_init_for_display_name()を使って、ソケットの表示名を$XDG_RUNTIME_DIRとつなげるなどして、UNIXソケットのパスを得る- wl_socket_lock()
- _wl_display_add_socket()
- ここまで来たら成功扱い、ソケットの表示名(wayland-0など)を return
int wl_socket_lock(struct wl_socket *socket)
snprintf()を使ってsocket->lock_addrにソケットパス +LOCK_SUFFIX (== ".lock")を書き込みlock_addrは$XDG_RUNTIME_DIR/wayland-%d.lockになるというわけ
socket->fd_lock = open(lock_addr)で、lockファイルを開く or 作成するopen()にはO_CREATが付いている(ファイルが存在しなかったら作成)
flock(socket_fd_lock, LOCK_EX, LOCK_NB)- EXclusive & NonBlockingなロック
lstat(socket_addr.sun_path, &socket_stat)を呼ぶ。ENOENT以外のエラーなら中断。socket_stat.st.modeのS_IWUSRあるいはS_IWGRPが立っていたらunlink()lstat()はリンクを辿らないstat()- これから作成するUNIXソケットのパスにファイルがあるかどうか確かめている。
ENOENT、つまりNo Entry(存在しない)ならソケットを作っても問題ない - エラーが出ないということはファイルが存在するということ。ユーザーまたはユーザーが所属するグループに書き込み権限が与えられていたら
unlink()で削除する- この行に到達しているということは
flock()が成功しているということになるため、他のコンポジタが使用中であると考えなくて良い。つまり古いソケットが残り続けていると考えて削除してもOKということかな
- この行に到達しているということは
int _wl_display_add_socket(struct wl_display *display, struct wl_socket *s)
/wl_display_add_socket(_auto)?/ から呼ばれる
s->fd = socket(PF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC)でソケットを作成して、bind()して、listen()する- wl_event_loop_add_fd(-, s->fd, -, socket_data, -)
int socket_data(int fd, uint32_t mask, void *data)
wl_display_add_socket_fd() あるいは _wl_display_add_socket() が wl_event_loop_add_fd() を呼ぶ時、この第4引数として利用される
event-loop.c
wl_event_source* wl_event_loop_add_fd(_, int fd, _, wl_event_loop_fd_func_t func, _)
wl_event_source_fd にデータを詰めて add_source() を呼ぶ
add_source() は epoll_ctl() を使って fd を loop->epoll_fd に登録するもの
int wl_event_loop_dispatch(struct wl_event_loop *loop, int timeout)
epoll_wait(loop->epoll_fd) している
wl_event_loop* wl_event_loop_create()
wl_display_create() から呼ばれる(display->loop = wl_event_loop_create())
loop->epoll_fd = epoll_create1(EPOLL_CLOEXEC) している
Client
wayland-client.c
Tree
wl_display_add_socket_fd()でWaylandソケットの登録wl_event_loop_add_fd()によりWaylandソケットがイベントループに追加