this repo has no description
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

xtrace: Add special printing functions for `select`

Now xtrace can tell you which descriptors were passed in to `select` as
well as which descriptors `select` returned as being active.

+146 -6
+146 -6
src/xtrace/bsd_trace.cpp
··· 3 3 #include <fcntl.h> 4 4 #include <sys/mman.h> 5 5 #include <pthread.h> 6 + #include <limits.h> 6 7 7 8 #define PRIVATE 1 8 9 #include <spawn_private.h> ··· 24 25 static void print_kevent64_args(int nr, void* args[]); 25 26 static void print_kevent_qos_return(int nr, uintptr_t rv); 26 27 static void print_kevent_qos_args(int nr, void* args[]); 28 + 29 + static void print_select_return(int nr, uintptr_t rv); 30 + static void print_select_args(int nr, void* args[]); 27 31 28 32 static void print_timespec(const struct timespec* timespec); 29 33 ··· 97 101 [89] = { "getdtablesize", print_args, print_errno_num }, 98 102 [90] = { "dup2", print_args, print_errno_num }, 99 103 [92] = { "fcntl", print_args, print_errno_num }, 100 - [93] = { "select", print_args, print_errno_num }, 104 + [93] = { "select", print_select_args, print_select_return }, 101 105 [95] = { "fsync", print_args, print_errno_num }, 102 106 [96] = { "setpriority", print_args, print_errno_num }, 103 107 [97] = { "socket", print_args, print_errno_num }, ··· 705 709 [89] = { 0, { } }, // getdtablesize 706 710 [90] = { 2, { print_arg_int, print_arg_int } }, // dup2 707 711 [92] = { 3, { print_arg_int, print_arg_int, print_arg_int } }, // fcntl 708 - [93] = { 5, { print_arg_int, print_arg_ptr, print_arg_ptr, print_arg_ptr, print_arg_ptr } }, // select 712 + // select is special 709 713 [95] = { 1, { print_arg_int } }, // fsync 710 714 [96] = { 3, { print_arg_int, print_arg_int, print_arg_int } }, // setpriority 711 715 [97] = { 3, { print_arg_int, print_arg_int, print_arg_int } }, // socket ··· 1464 1468 }; 1465 1469 1466 1470 DEFINE_XTRACE_TLS_VAR(void*, kevent_stored_list, NULL); 1471 + DEFINE_XTRACE_TLS_VAR(void*, kevent64_stored_list, NULL); 1472 + DEFINE_XTRACE_TLS_VAR(void*, kevent_qos_stored_list, NULL); 1467 1473 1468 1474 enum class kevent_type { 1469 1475 kevent, ··· 1472 1478 }; 1473 1479 1474 1480 static void print_kevent_return_common(int nr, uintptr_t rv, kevent_type type) { 1475 - void* event_list = get_kevent_stored_list(); 1481 + void* event_list; 1476 1482 int ret = (intptr_t)rv; 1477 1483 1478 - set_kevent_stored_list(NULL); 1484 + switch (type) { 1485 + case kevent_type::kevent: 1486 + event_list = get_kevent_stored_list(); 1487 + set_kevent_stored_list(NULL); 1488 + break; 1489 + case kevent_type::kevent64: 1490 + event_list = get_kevent64_stored_list(); 1491 + set_kevent64_stored_list(NULL); 1492 + break; 1493 + case kevent_type::kevent_qos: 1494 + event_list = get_kevent_qos_stored_list(); 1495 + set_kevent_qos_stored_list(NULL); 1496 + break; 1497 + } 1479 1498 1480 1499 if (ret < 0) { 1481 1500 print_errno(nr, rv); ··· 1572 1591 const struct timespec* timeout = (const struct timespec*)args[6]; 1573 1592 bool printed_something = false; 1574 1593 1575 - set_kevent_stored_list(event_list); 1594 + set_kevent64_stored_list(event_list); 1576 1595 1577 1596 xtrace_log("%d, change_list = {", kq); 1578 1597 ··· 1625 1644 unsigned int flags = (uintptr_t)args[7]; 1626 1645 bool printed_something = false; 1627 1646 1628 - set_kevent_stored_list(event_list); 1647 + set_kevent_qos_stored_list(event_list); 1629 1648 1630 1649 xtrace_log("%d, change_list = {", kq); 1631 1650 ··· 1666 1685 xtrace_log("NULL"); 1667 1686 } 1668 1687 }; 1688 + 1689 + static void print_timeval(const struct timeval* timeval) { 1690 + if (timeval) { 1691 + xtrace_log("(%ld s, %d ns)", timeval->tv_sec, timeval->tv_usec); 1692 + } else { 1693 + xtrace_log("NULL"); 1694 + } 1695 + }; 1696 + 1697 + struct select_fdsets { 1698 + fd_set* readfds; 1699 + fd_set* writefds; 1700 + fd_set* exceptfds; 1701 + int max_fd; 1702 + }; 1703 + 1704 + DEFINE_XTRACE_TLS_VAR(select_fdsets, stored_select_fdsets, ((struct select_fdsets){NULL, NULL, NULL, -1})); 1705 + 1706 + static void print_fdset(const fd_set* set, int max_fd) { 1707 + bool isFirst = true; 1708 + xtrace_log("{"); 1709 + if (set) { 1710 + for (size_t index = 0; index < sizeof(set->fds_bits) / sizeof(*set->fds_bits); ++index) { 1711 + bool shouldBreak = false; 1712 + for (size_t bit = 0; bit < sizeof(*set->fds_bits) * 8; ++bit) { 1713 + int fd = (index * sizeof(*set->fds_bits) * 8) + bit; 1714 + if (fd >= max_fd) { 1715 + shouldBreak = true; 1716 + break; 1717 + } 1718 + if ((set->fds_bits[index] & (1U << bit)) != 0) { 1719 + if (isFirst) { 1720 + isFirst = false; 1721 + xtrace_log(" "); 1722 + } else { 1723 + xtrace_log(", "); 1724 + } 1725 + xtrace_log("%d", fd); 1726 + } 1727 + } 1728 + if (shouldBreak) { 1729 + break; 1730 + } 1731 + } 1732 + } 1733 + if (!isFirst) { 1734 + xtrace_log(" "); 1735 + } 1736 + xtrace_log("}"); 1737 + }; 1738 + 1739 + static void print_select_return(int nr, uintptr_t rv) { 1740 + auto stored = get_ptr_stored_select_fdsets(); 1741 + int ret = (int)rv; 1742 + bool isFirst = true; 1743 + 1744 + if (ret < 0) { 1745 + print_errno(nr, rv); 1746 + } else { 1747 + xtrace_log("%d descriptors: ", ret); 1748 + 1749 + if (stored->readfds) { 1750 + if (isFirst) { 1751 + isFirst = false; 1752 + } else { 1753 + xtrace_log(", "); 1754 + } 1755 + xtrace_log("read "); 1756 + print_fdset(stored->readfds, stored->max_fd); 1757 + } 1758 + 1759 + if (stored->writefds) { 1760 + if (isFirst) { 1761 + isFirst = false; 1762 + } else { 1763 + xtrace_log(", "); 1764 + } 1765 + xtrace_log("write "); 1766 + print_fdset(stored->writefds, stored->max_fd); 1767 + } 1768 + 1769 + if (stored->exceptfds) { 1770 + if (isFirst) { 1771 + isFirst = false; 1772 + } else { 1773 + xtrace_log(", "); 1774 + } 1775 + xtrace_log("except "); 1776 + print_fdset(stored->exceptfds, stored->max_fd); 1777 + } 1778 + } 1779 + 1780 + stored->readfds = NULL; 1781 + stored->writefds = NULL; 1782 + stored->exceptfds = NULL; 1783 + stored->max_fd = -1; 1784 + }; 1785 + 1786 + static void print_select_args(int nr, void* args[]) { 1787 + auto stored = get_ptr_stored_select_fdsets(); 1788 + 1789 + int nfds = (intptr_t)args[0]; 1790 + fd_set* readfds = (fd_set*)args[1]; 1791 + fd_set* writefds = (fd_set*)args[2]; 1792 + fd_set* exceptfds = (fd_set*)args[3]; 1793 + struct timeval* timeout = (struct timeval*)args[4]; 1794 + 1795 + xtrace_log("nfds = %d, readfds = ", nfds); 1796 + print_fdset(readfds, nfds); 1797 + xtrace_log(", writefds = "); 1798 + print_fdset(writefds, nfds); 1799 + xtrace_log(", exceptfds = "); 1800 + print_fdset(exceptfds, nfds); 1801 + xtrace_log(", timeout = "); 1802 + print_timeval(timeout); 1803 + 1804 + stored->readfds = readfds; 1805 + stored->writefds = writefds; 1806 + stored->exceptfds = exceptfds; 1807 + stored->max_fd = nfds; 1808 + };