@@ -259,6 +259,13 @@ static void get_tcp_info(struct uwsgi_socket *uwsgi_sock) {
259
259
260
260
#ifdef UNBIT
261
261
#define SIOBKLGQ 0x8908
262
+ #else
263
+
264
+ #include <linux/netlink.h>
265
+ #include <linux/rtnetlink.h>
266
+ #include <linux/unix_diag.h>
267
+ #include <linux/sock_diag.h>
268
+
262
269
#endif
263
270
264
271
#ifdef SIOBKLGQ
@@ -272,7 +279,141 @@ static void get_linux_unbit_SIOBKLGQ(struct uwsgi_socket *uwsgi_sock) {
272
279
uwsgi_sock -> max_queue = (uint64_t ) uwsgi .listen_queue ;
273
280
}
274
281
}
282
+ #else
283
+
284
+ static int get_socket_inode_from_fd (int fd ) {
285
+ int inode = -1 ;
286
+ char source_link_path [32 ];
287
+ char link_target [32 ];
288
+ sprintf (source_link_path , "/proc/self/fd/%i" , fd );
289
+ if (readlink (source_link_path , link_target , 32 ) > 0 )
290
+ sscanf (link_target , "socket:[%i]" , & inode );
291
+ return inode ;
292
+ }
293
+
294
+ static void send_netlink_query_for_inode (int fd , int target_ino ) {
295
+ struct sockaddr_nl nladdr = {.nl_family = AF_NETLINK };
296
+ struct {
297
+ struct nlmsghdr nlh ;
298
+ struct unix_diag_req udr ;
299
+ } req = {
300
+ .nlh = {
301
+ .nlmsg_len = sizeof (req ),
302
+ .nlmsg_type = SOCK_DIAG_BY_FAMILY ,
303
+ .nlmsg_flags = NLM_F_REQUEST
304
+ },
305
+ .udr = {
306
+ .sdiag_family = AF_UNIX ,
307
+ .udiag_show = UDIAG_SHOW_RQLEN ,
308
+ .udiag_ino = target_ino ,
309
+ .udiag_cookie = {-1 , -1 }
310
+ }
311
+ };
312
+ struct iovec iov = {.iov_base = & req , .iov_len = sizeof (req )};
313
+ struct msghdr msg = {
314
+ .msg_name = & nladdr ,
315
+ .msg_namelen = sizeof (nladdr ),
316
+ .msg_iov = & iov ,
317
+ .msg_iovlen = 1
318
+ };
319
+
320
+ for (;;) {
321
+ if (sendmsg (fd , & msg , 0 ) < 0 ) {
322
+ if (errno == EINTR )
323
+ continue ;
324
+
325
+ perror ("sendmsg" );
326
+ return ;
327
+ }
328
+
329
+ return ;
330
+ }
331
+ }
332
+
333
+ static int receive_netlink_answers (int fd , uint64_t * current_queue , uint64_t * max_queue ) {
334
+ long buf [8192 / sizeof (long )];
335
+ struct sockaddr_nl nladdr ;
336
+ struct iovec iov = {.iov_base = buf , .iov_len = sizeof (buf )};
337
+ int flags = 0 ;
338
+
339
+ for (;;) {
340
+ struct msghdr msg = {
341
+ .msg_name = & nladdr ,
342
+ .msg_namelen = sizeof (nladdr ),
343
+ .msg_iov = & iov ,
344
+ .msg_iovlen = 1
345
+ };
346
+
347
+ ssize_t ret = recvmsg (fd , & msg , flags );
348
+
349
+ if (ret < 0 ) {
350
+ if (errno == EINTR )
351
+ continue ;
352
+
353
+ perror ("recvmsg" );
354
+ return -1 ;
355
+ }
356
+ if (ret == 0 )
357
+ return 0 ;
358
+
359
+ if (nladdr .nl_family != AF_NETLINK ) {
360
+ fputs ("!AF_NETLINK\n" , stderr );
361
+ return -1 ;
362
+ }
363
+
364
+ const struct nlmsghdr * h = (struct nlmsghdr * )buf ;
365
+
366
+ if (!NLMSG_OK (h , ret )) {
367
+ fputs ("!NLMSG_OK\n" , stderr );
368
+ return -1 ;
369
+ }
370
+
371
+ for (; NLMSG_OK (h , ret ); h = NLMSG_NEXT (h , ret )) {
372
+ if (h -> nlmsg_type == NLMSG_DONE )
373
+ return 0 ;
374
+ if (h -> nlmsg_type == NLMSG_ERROR ) {
375
+ const struct nlmsgerr * err = NLMSG_DATA (h );
376
+ if (h -> nlmsg_len < NLMSG_LENGTH (sizeof (* err ))) {
377
+ fputs ("NLMSG_ERROR\n" , stderr );
378
+ } else {
379
+ errno = - err -> error ;
380
+ perror ("NLMSG_ERROR" );
381
+ }
382
+ return -1 ;
383
+ }
384
+ if (h -> nlmsg_type != SOCK_DIAG_BY_FAMILY ) {
385
+ fprintf (stderr , "unexpected nlmsg_type %u\n" , (unsigned )h -> nlmsg_type );
386
+ return -1 ;
387
+ }
388
+
389
+ // Now extract queue len from results
390
+ const struct unix_diag_msg * diag = NLMSG_DATA (h );
391
+ unsigned int rta_len = h -> nlmsg_len - NLMSG_LENGTH (sizeof (* diag ));
392
+
393
+ for (struct rtattr * attr = (struct rtattr * )(diag + 1 ); RTA_OK (attr , rta_len ); attr = RTA_NEXT (attr , rta_len )) {
394
+ switch (attr -> rta_type ) {
395
+ case UNIX_DIAG_RQLEN :
396
+ * current_queue = ((struct unix_diag_rqlen * ) RTA_DATA (attr ))-> udiag_rqueue ;
397
+ * max_queue = ((struct unix_diag_rqlen * ) RTA_DATA (attr ))-> udiag_wqueue ;
398
+ break ;
399
+ }
400
+ }
401
+ }
402
+ return 0 ;
403
+ }
404
+ }
405
+
406
+ static void get_linux_unix_socket_queue (struct uwsgi_socket * uwsgi_sock ) {
407
+ int fd = uwsgi_sock -> fd ;
408
+ int inode = get_socket_inode_from_fd (fd );
409
+ int diag_socket = socket (AF_NETLINK , SOCK_RAW | SOCK_CLOEXEC , NETLINK_SOCK_DIAG );
410
+ send_netlink_query_for_inode (diag_socket , inode );
411
+ receive_netlink_answers (diag_socket , & uwsgi_sock -> queue , & uwsgi_sock -> max_queue );
412
+ close (diag_socket );
413
+ }
414
+
275
415
#endif
416
+
276
417
#endif
277
418
278
419
static void master_check_listen_queue () {
@@ -282,15 +423,16 @@ static void master_check_listen_queue() {
282
423
while (uwsgi_sock ) {
283
424
if (uwsgi_sock -> family == AF_INET ) {
284
425
get_tcp_info (uwsgi_sock );
285
- }
426
+ }
427
+ else if (uwsgi_sock -> family == AF_UNIX ) {
286
428
#ifdef __linux__
287
429
#ifdef SIOBKLGQ
288
- else if (uwsgi_sock -> family == AF_UNIX ) {
289
- get_linux_unbit_SIOBKLGQ ( uwsgi_sock );
290
- }
430
+ get_linux_unbit_SIOBKLGQ (uwsgi_sock );
431
+ #else
432
+ get_linux_unix_socket_queue ( uwsgi_sock );
291
433
#endif
292
434
#endif
293
-
435
+ }
294
436
if (uwsgi_sock -> queue > backlog ) {
295
437
backlog = uwsgi_sock -> queue ;
296
438
}
0 commit comments