|
41 | 41 | destroy/1, |
42 | 42 | negative/1, |
43 | 43 | error_info/1, |
| 44 | + is_bif_traced/1, |
| 45 | + |
44 | 46 | end_of_list/1]). |
45 | 47 |
|
46 | 48 | -include_lib("common_test/include/ct.hrl"). |
@@ -78,6 +80,8 @@ all() -> |
78 | 80 | destroy, |
79 | 81 | negative, |
80 | 82 | error_info, |
| 83 | + is_bif_traced, |
| 84 | + |
81 | 85 | end_of_list]. |
82 | 86 |
|
83 | 87 | init_per_suite(Config) -> |
@@ -1842,6 +1846,86 @@ tracer_loop(Name, Tester) -> |
1842 | 1846 | tracer_loop(Name, Tester). |
1843 | 1847 |
|
1844 | 1848 |
|
| 1849 | +%% OTP-19840: Verify setting/clearing of 'is_bif_traced' in export entry |
| 1850 | +%% works correctly for multiple sessions. |
| 1851 | +is_bif_traced(_Config) -> |
| 1852 | + CallTypes = [global, local], |
| 1853 | + [is_bif_traced_do(CT1, CT2, CT3) |
| 1854 | + || CT1 <- CallTypes, CT2 <- CallTypes, CT3 <- CallTypes], |
| 1855 | + ok. |
| 1856 | + |
| 1857 | +is_bif_traced_do(CT1, CT2, CT3) -> |
| 1858 | + io:format("CT1=~w, CT2=~w, CT3=~w\n", [CT1, CT2, CT3]), |
| 1859 | + |
| 1860 | + Tester = self(), |
| 1861 | + TracerFun = fun F() -> receive M -> Tester ! {self(), M} end, F() end, |
| 1862 | + T1 = spawn_link(TracerFun), |
| 1863 | + S1 = trace:session_create(one, T1, []), |
| 1864 | + |
| 1865 | + %% A benign BIF call that does not get optimized away |
| 1866 | + BIF = {erlang,phash2,1}, |
| 1867 | + {M,F,A} = BIF, |
| 1868 | + true = erlang:is_builtin(M,F,A), |
| 1869 | + |
| 1870 | + trace:function(S1, BIF, true, [CT1]), |
| 1871 | + trace:process(S1, self(), true, [call]), |
| 1872 | + |
| 1873 | + M:F("S1"), |
| 1874 | + {T1, {trace,Tester,call,{M,F,["S1"]}}} = receive_any(), |
| 1875 | + |
| 1876 | + T2 = spawn_link(TracerFun), |
| 1877 | + S2 = trace:session_create(two, T2, []), |
| 1878 | + trace:function(S2, BIF, true, [CT2]), |
| 1879 | + trace:process(S2, self(), true, [call]), |
| 1880 | + |
| 1881 | + M:F("S1 & S2"), |
| 1882 | + receive_parallel_list( |
| 1883 | + [[{T1, {trace,Tester,call,{M,F,["S1 & S2"]}}}], |
| 1884 | + [{T2, {trace,Tester,call,{M,F,["S1 & S2"]}}}]]), |
| 1885 | + |
| 1886 | + T3 = spawn_link(TracerFun), |
| 1887 | + S3 = trace:session_create(three, T3, []), |
| 1888 | + trace:function(S3, BIF, true, [CT3]), |
| 1889 | + trace:process(S3, self(), true, [call]), |
| 1890 | + |
| 1891 | + M:F("S1 & S2 & S3"), |
| 1892 | + receive_parallel_list( |
| 1893 | + [[{T1, {trace,Tester,call,{M,F,["S1 & S2 & S3"]}}}], |
| 1894 | + [{T2, {trace,Tester,call,{M,F,["S1 & S2 & S3"]}}}], |
| 1895 | + [{T3, {trace,Tester,call,{M,F,["S1 & S2 & S3"]}}}]]), |
| 1896 | + |
| 1897 | + %% Remove not last BIF trace nicely |
| 1898 | + trace:function(S1, BIF, false, [CT1]), |
| 1899 | + M:F("S2 & S3"), |
| 1900 | + receive_parallel_list( |
| 1901 | + [[{T2, {trace,Tester,call,{M,F,["S2 & S3"]}}}], |
| 1902 | + [{T3, {trace,Tester,call,{M,F,["S2 & S3"]}}}]]), |
| 1903 | + |
| 1904 | + %% Remove not last BIF trace by session destruction |
| 1905 | + trace:session_destroy(S2), |
| 1906 | + M:F("S3"), |
| 1907 | + receive_parallel_list( |
| 1908 | + [[{T3, {trace,Tester,call,{M,F,["S3"]}}}]]), |
| 1909 | + |
| 1910 | + %% Remove last BIF trace nicely |
| 1911 | + trace:function(S3, BIF, false, [CT3]), |
| 1912 | + M:F("no trace"), |
| 1913 | + receive_nothing(), |
| 1914 | + |
| 1915 | + trace:function(S1, BIF, true, [CT1]), |
| 1916 | + M:F("S1"), |
| 1917 | + receive_parallel_list( |
| 1918 | + [[{T1, {trace,Tester,call,{M,F,["S1"]}}}]]), |
| 1919 | + |
| 1920 | + %% Remove last BIF trace by session destruction |
| 1921 | + trace:session_destroy(S1), |
| 1922 | + M:F("no trace"), |
| 1923 | + receive_nothing(), |
| 1924 | + |
| 1925 | + trace:session_destroy(S3), |
| 1926 | + ok. |
| 1927 | + |
| 1928 | + |
1845 | 1929 | receive_any() -> |
1846 | 1930 | receive_any(1000). |
1847 | 1931 |
|
|
0 commit comments