前提:Waylandはコンポジタ(server)とクライアントのIPCUNIXソケットを使っている。たいてい $XDG_RUNTIME_DIR/wayland-%d がそう

Server

wayland-server.c

const char* wl_display_add_socket_auto(wl_display*)

  1. snprintf() を使って、ソケットの表示名を wayland-%d (0から開始)という形式で取得
  2. wl_socket_init_for_display_name() を使って、ソケットの表示名を $XDG_RUNTIME_DIR とつなげるなどして、UNIXソケットのパスを得る
  3. wl_socket_lock()
  4. _wl_display_add_socket()
  5. ここまで来たら成功扱い、ソケットの表示名(wayland-0など)を return

int wl_socket_lock(struct wl_socket *socket)

  1. snprintf() を使って socket->lock_addr にソケットパス + LOCK_SUFFIX (== ".lock") を書き込み
    1. lock_addr$XDG_RUNTIME_DIR/wayland-%d.lock になるというわけ
  2. socket->fd_lock = open(lock_addr) で、lockファイルを開く or 作成する
    1. open() には O_CREAT が付いている(ファイルが存在しなかったら作成)
  3. flock(socket_fd_lock, LOCK_EX, LOCK_NB)
    1. EXclusive & NonBlockingなロック
  4. lstat(socket_addr.sun_path, &socket_stat) を呼ぶ。ENOENT 以外のエラーなら中断。socket_stat.st.modeS_IWUSR あるいは S_IWGRP が立っていたら unlink()
    1. lstat() はリンクを辿らない stat()
    2. これから作成するUNIXソケットのパスにファイルがあるかどうか確かめている。ENOENT、つまりNo Entry(存在しない)ならソケットを作っても問題ない
    3. エラーが出ないということはファイルが存在するということ。ユーザーまたはユーザーが所属するグループに書き込み権限が与えられていたら unlink() で削除する
      1. この行に到達しているということは flock() が成功しているということになるため、他のコンポジタが使用中であると考えなくて良い。つまり古いソケットが残り続けていると考えて削除してもOKということかな

int _wl_display_add_socket(struct wl_display *display, struct wl_socket *s)

/wl_display_add_socket(_auto)?/ から呼ばれる

  1. s->fd = socket(PF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC) でソケットを作成して、bind() して、 listen() する
  2. 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() を使って fdloop->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

  1. wl_display_add_socket_fd() でWaylandソケットの登録
  2. wl_event_loop_add_fd() によりWaylandソケットがイベントループに追加