Requirements:
- determine the PID of the peer compositor process for a display connection on the client side
- must run under Linux
- optionally determines the process name
Since this is not directly supported by the API, you can
- get the file descriptor of the display context (
wl_display_get_fd
)
- use the file descriptor to read the associated PID of the peer process (
getsockopt
with the SO_PEERCRED
option, see e.g. this nice SO answer)
- finally, you can get the process name by reading
/proc/<pid>/comm
.
You could also retrieve the process command line if you need more information.
However, the output of the following test program would look like this under Ubuntu 22.04 LTS
:
pid: 1733, process name: gnome-shell
Self-contained Example in C
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wayland-client.h>
#include <sys/socket.h>
#include <errno.h>
#define PROCESS_NAME_MAX_LENGTH 1024
static pid_t pid_from_fd(int fd) {
struct ucred ucred;
socklen_t len = sizeof(struct ucred);
if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &len) == -1) {
perror("getsockopt failed");
exit(-1);
}
return ucred.pid;
}
static char *process_name_from_pid(const pid_t pid) {
char *name = malloc(PROCESS_NAME_MAX_LENGTH);
if (!name) {
perror("malloc failed");
exit(-1);
}
char proc_buf[64];
sprintf(proc_buf, "/proc/%d/comm", pid);
FILE *fp;
if ((fp = fopen(proc_buf, "r")) == NULL) {
fprintf(stderr, "opening '%s' failed: %s\n", proc_buf, strerror(errno));
exit(-1);
}
if (fgets(name, PROCESS_NAME_MAX_LENGTH, fp) == NULL) {
fprintf(stderr, "reading '%s' failed\n", proc_buf);
exit(-1);
}
name[strcspn(name, "\n")] = 0;
fclose(fp);
return name;
}
int main(void) {
struct wl_display *display = wl_display_connect(NULL);
if (display == NULL) {
fprintf(stderr, "can't connect to display\n");
exit(-1);
}
int fd = wl_display_get_fd(display);
pid_t pid = pid_from_fd(fd);
char *process_name = process_name_from_pid(pid);
printf("pid: %d, process name: %s\n", pid, process_name);
free(process_name);
wl_display_disconnect(display);
return 0;
}