As I understand, normally when a netlink socket is opened per process,
nl_pid is set to 0 and the kernel would pick the right portid. However
it is not true for netlink-per-thread case, where PID value will be
shared among all threads.
There is no "the right" portid. Identification of portids with process ids is a convention, consistent with the kernel's default behavior when it assigns the portid, not a rule. Applications, whether single- or multi-threaded, are free to request arbitrary port ids within the allowed range of port ids.
Moreover, when a process, whether single- or multi-threaded, binds multiple netlink sockets and delegates portid selection to the kernel, the kernel can be relied upon to assign a unique portid to each.
Besides I think pthread_self() << 16 | getpid()
is not portable.
You are correct. For that to have well-defined behavior in the general case, pthread_t
, the return type of pthread_self()
, would need to be an unsigned integer type, but POSIX does not require it to be even an integer, signedness notwithstanding.
Netlink is Linux-specific, and that does limit the scope you need to care about. Still, there have been more than one pthreads implementation for Linux, there may be new ones in the future, and because this detail is unspecified it is conceivable that implementations will change the type between versions.
What is the right way to set nl_pid in this case?
I would say that the best option for choosing netlink portids is almost always to let the kernel assign them, as you concluded in comments. Including in single-threaded applications. This is not a question of the process's file descriptor table, however, because portids are not file descriptors. In particular, unlike file descriptors, portids are system-wide. This is all the more reason to let the kernel choose.