Compare commits
602 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
16d6a0b49d | ||
|
|
436c04048e | ||
|
|
feddddb56b | ||
|
|
f61f9c29d8 | ||
|
|
843b64faf5 | ||
|
|
85b526f56a | ||
|
|
8a94b7b2ec | ||
|
|
b807450e98 | ||
|
|
82cdfb75ff | ||
|
|
dcace2a393 | ||
|
|
378edb28f4 | ||
|
|
7894072528 | ||
|
|
abe59d6319 | ||
|
|
e399e00e78 | ||
|
|
51477bc711 | ||
|
|
23632e9104 | ||
|
|
a6ddf41edf | ||
|
|
82351168b3 | ||
|
|
bc19beadbd | ||
|
|
f15c602bd0 | ||
|
|
0f31978c30 | ||
|
|
a2ba04f83f | ||
|
|
8fb9cb9194 | ||
|
|
be8eec8c5a | ||
|
|
e59e2a9e49 | ||
|
|
ec5a4b54f7 | ||
|
|
beebf02cf6 | ||
|
|
a94f2ad2b7 | ||
|
|
3d78d121f4 | ||
|
|
e8969bff6c | ||
|
|
7b4cf04a91 | ||
|
|
acebb97490 | ||
|
|
88201044ed | ||
|
|
72d9abccd7 | ||
|
|
16e6e84dcc | ||
|
|
7752218db2 | ||
|
|
88baee1a35 | ||
|
|
264bb335af | ||
|
|
6af08fb527 | ||
|
|
2494c088f0 | ||
|
|
467859c2ba | ||
|
|
69bad8201b | ||
|
|
c431bc39c3 | ||
|
|
14644080c8 | ||
|
|
3d0578e6eb | ||
|
|
61c966cf0b | ||
|
|
b7d07d78e9 | ||
|
|
556a0f1f0f | ||
|
|
b1d30f9489 | ||
|
|
c6d43bea09 | ||
|
|
31ea3411cc | ||
|
|
d05744e3ed | ||
|
|
1b084f7bbe | ||
|
|
5dcef22c62 | ||
|
|
15e3f84678 | ||
|
|
2907f6d69e | ||
|
|
c6b67af390 | ||
|
|
7b75935b00 | ||
|
|
2d8371a06e | ||
|
|
d4ab6fbba4 | ||
|
|
e129cd7fda | ||
|
|
a3abfbcb08 | ||
|
|
64f4502b9b | ||
|
|
0caf5bb876 | ||
|
|
94e467ad93 | ||
|
|
078180e13d | ||
|
|
e1095c7a43 | ||
|
|
058c49b7ba | ||
|
|
7e6590f31d | ||
|
|
9cf0710d71 | ||
|
|
52a9243317 | ||
|
|
18d48bc13c | ||
|
|
fbe2d85bd5 | ||
|
|
be0b00a80d | ||
|
|
bfbd6db0d6 | ||
|
|
8be336f4ee | ||
|
|
7c3abfbf1e | ||
|
|
1f36b01ed0 | ||
|
|
8d957c56b3 | ||
|
|
0be52c8251 | ||
|
|
1cbffcbd5d | ||
|
|
670e75ee7e | ||
|
|
f55efb2f38 | ||
|
|
88b874e63c | ||
|
|
473dafc593 | ||
|
|
65e3735320 | ||
|
|
f806be87d3 | ||
|
|
bcc6d1c1fc | ||
|
|
675a5a5396 | ||
|
|
5467ec969a | ||
|
|
511e202e13 | ||
|
|
d2e56a5e8d | ||
|
|
cc2e0aa3cf | ||
|
|
e1a5465255 | ||
|
|
32603fd5ff | ||
|
|
1c778bd001 | ||
|
|
5bb19f35ea | ||
|
|
88af4a87d2 | ||
|
|
9dddebab0d | ||
|
|
a49f264dff | ||
|
|
44e61dab7e | ||
|
|
0a00e80c36 | ||
|
|
5ff1fc724f | ||
|
|
f00d4b6775 | ||
|
|
5cbc82e369 | ||
|
|
58dfb6c89b | ||
|
|
b5eb41d882 | ||
|
|
c869cd1d8a | ||
|
|
5cc7175514 | ||
|
|
3e1733a053 | ||
|
|
8809d1df8d | ||
|
|
1790abb3b2 | ||
|
|
31d9165999 | ||
|
|
27134547ff | ||
|
|
1eac3310ad | ||
|
|
a53e7877e4 | ||
|
|
c84a2dbe03 | ||
|
|
88ab6e78da | ||
|
|
5537d6a689 | ||
|
|
e78e29c231 | ||
|
|
9b3b61f606 | ||
|
|
a6a987c0de | ||
|
|
727ee7237e | ||
|
|
4e310d0f90 | ||
|
|
f23037fe21 | ||
|
|
e5cb1d3d3d | ||
|
|
63b22be083 | ||
|
|
badecdca14 | ||
|
|
83306585ff | ||
|
|
18266a6969 | ||
|
|
0c36b16d1b | ||
|
|
e4d47c5357 | ||
|
|
593aa3b2f6 | ||
|
|
47c833675b | ||
|
|
372e4c645e | ||
|
|
6ab153cf8e | ||
|
|
9678211c24 | ||
|
|
5d1ccc12c4 | ||
|
|
f56f21d7da | ||
|
|
ecc11611d3 | ||
|
|
f279d9e6c6 | ||
|
|
ae6e146775 | ||
|
|
90648ea3e5 | ||
|
|
2780b87d56 | ||
|
|
e37539a46c | ||
|
|
7c491bde32 | ||
|
|
6621fe045a | ||
|
|
36f0789d83 | ||
|
|
fedfa9893e | ||
|
|
ba24986f8d | ||
|
|
eb5af8e3c0 | ||
|
|
1ee1063402 | ||
|
|
541329d51f | ||
|
|
d2d92b74a8 | ||
|
|
c8d4a87f49 | ||
|
|
ab3ecf6565 | ||
|
|
287987b37c | ||
|
|
10ccd08471 | ||
|
|
bf61390769 | ||
|
|
520eb622f0 | ||
|
|
497f3168d1 | ||
|
|
8083ab26e0 | ||
|
|
c0a61c3bb3 | ||
|
|
f50ae53c42 | ||
|
|
17219b8f39 | ||
|
|
46c0e1769b | ||
|
|
4fce06ec96 | ||
|
|
77e4cd5b18 | ||
|
|
d05ed869bb | ||
|
|
abc9767034 | ||
|
|
6adeeacee7 | ||
|
|
f55628eed0 | ||
|
|
3ecce91410 | ||
|
|
cc23e204d7 | ||
|
|
e0c5fc8714 | ||
|
|
91ba13054a | ||
|
|
b0816180e3 | ||
|
|
fa6745b4f2 | ||
|
|
6912038d72 | ||
|
|
2c15345016 | ||
|
|
ff9587991f | ||
|
|
625d3d275a | ||
|
|
a7c44d6748 | ||
|
|
e8458b2402 | ||
|
|
6b56200cc8 | ||
|
|
cc9e96147f | ||
|
|
507f3046d1 | ||
|
|
7b9e37c7da | ||
|
|
009d7414bc | ||
|
|
08a1e7fd23 | ||
|
|
99e576612d | ||
|
|
e9f29cb984 | ||
|
|
c858a14764 | ||
|
|
e0327e1d50 | ||
|
|
3530bcc303 | ||
|
|
0f2d7e784a | ||
|
|
bb6fbcf6e7 | ||
|
|
10f313631c | ||
|
|
129362f356 | ||
|
|
3f7191e5c2 | ||
|
|
535efdf319 | ||
|
|
f98516ddd5 | ||
|
|
3b6a1a14ca | ||
|
|
a7cbda92b6 | ||
|
|
a407b232f0 | ||
|
|
160cd5629e | ||
|
|
7d092913b3 | ||
|
|
a9381cdb03 | ||
|
|
e72a91e063 | ||
|
|
64bd28f5ba | ||
|
|
1dd0ab1315 | ||
|
|
8861a97efa | ||
|
|
51a22f60d6 | ||
|
|
8a499e1331 | ||
|
|
34db4c21b1 | ||
|
|
1479b76310 | ||
|
|
a7d5255122 | ||
|
|
12bd89bbc3 | ||
|
|
5e302730cd | ||
|
|
a5c01d4de3 | ||
|
|
de43f42735 | ||
|
|
fc70430b09 | ||
|
|
7ba94d3909 | ||
|
|
bfbe4e38d7 | ||
|
|
4785ad6337 | ||
|
|
6be130e1b8 | ||
|
|
f144429365 | ||
|
|
35da5ded3b | ||
|
|
b9421d7066 | ||
|
|
54d8364c24 | ||
|
|
d843b7cf7f | ||
|
|
e135dfe183 | ||
|
|
31e4b90c3c | ||
|
|
874363f652 | ||
|
|
f01219dfb7 | ||
|
|
f067f50ae4 | ||
|
|
4107b8d4db | ||
|
|
815693f715 | ||
|
|
97b7873cba | ||
|
|
be6b81a352 | ||
|
|
66160d6973 | ||
|
|
93efccf4ee | ||
|
|
77991a0761 | ||
|
|
f388908593 | ||
|
|
56fca44a4b | ||
|
|
a389393ffa | ||
|
|
7b34154cf2 | ||
|
|
da527d8d2a | ||
|
|
b8368a1441 | ||
|
|
c5f027d6be | ||
|
|
9956da1567 | ||
|
|
8ac649e2aa | ||
|
|
8d69f256d1 | ||
|
|
815dd8a25c | ||
|
|
dc1bb0088e | ||
|
|
197f453b76 | ||
|
|
d8669609d8 | ||
|
|
004dfd2d4b | ||
|
|
13148457a9 | ||
|
|
75f7de4010 | ||
|
|
fc4840ebc9 | ||
|
|
011a1ac1a3 | ||
|
|
56fada47f2 | ||
|
|
737f4f953f | ||
|
|
fef619608b | ||
|
|
663d88b677 | ||
|
|
c03569f0df | ||
|
|
2a4cab70ef | ||
|
|
d83fadaf09 | ||
|
|
d277f71333 | ||
|
|
c811169f91 | ||
|
|
4e416266f6 | ||
|
|
0d78f3c758 | ||
|
|
e2c8fed7b3 | ||
|
|
0a02887e62 | ||
|
|
65dc822d6c | ||
|
|
b3759772d2 | ||
|
|
65541f772f | ||
|
|
1b4bd9209e | ||
|
|
c97017dd1d | ||
|
|
2f82750098 | ||
|
|
e893cd6826 | ||
|
|
124d55c970 | ||
|
|
30c3ef9f6f | ||
|
|
55376b044b | ||
|
|
9c1de6e93f | ||
|
|
49d83c0301 | ||
|
|
d09441ca03 | ||
|
|
50b53cbd0d | ||
|
|
1230fad8f4 | ||
|
|
a939d643dd | ||
|
|
2f87d5c114 | ||
|
|
c5644368b5 | ||
|
|
ad523c20c7 | ||
|
|
f0bb7e40f0 | ||
|
|
7b43d70be4 | ||
|
|
c8fad2ac09 | ||
|
|
ca544ed6fc | ||
|
|
6df5a72151 | ||
|
|
3e0b846bdb | ||
|
|
4b0fe81758 | ||
|
|
1752791c9e | ||
|
|
2bf97f123f | ||
|
|
9179888c2b | ||
|
|
dde50f0e22 | ||
|
|
24d1d0802d | ||
|
|
6a9e4293d8 | ||
|
|
4002231bd9 | ||
|
|
7ada448d18 | ||
|
|
2f1614b128 | ||
|
|
b9b6db052b | ||
|
|
e8ec610f28 | ||
|
|
65c1402ee6 | ||
|
|
e7b9633170 | ||
|
|
1b01b786c0 | ||
|
|
8f32a14afa | ||
|
|
6d0d4a3e4d | ||
|
|
962b8e626c | ||
|
|
281e6185cc | ||
|
|
5bf18a6e88 | ||
|
|
4e766761d0 | ||
|
|
a4649f5078 | ||
|
|
d4f8a4ab5d | ||
|
|
b9789a452f | ||
|
|
07261493a7 | ||
|
|
03bb703741 | ||
|
|
ef6a9a624d | ||
|
|
d23a20f62c | ||
|
|
6f94701467 | ||
|
|
d1a2efc77b | ||
|
|
1a56f68451 | ||
|
|
e7ecd116e0 | ||
|
|
44b8153005 | ||
|
|
30fc896cc1 | ||
|
|
6ad347fae4 | ||
|
|
748d894e82 | ||
|
|
f70027cbdc | ||
|
|
8a5b0955de | ||
|
|
ff7dcd2654 | ||
|
|
3990fcad62 | ||
|
|
15e81386bf | ||
|
|
3f331e97da | ||
|
|
6e073ef5da | ||
|
|
f272082240 | ||
|
|
c51522c08f | ||
|
|
932092e95d | ||
|
|
c8a1e6132b | ||
|
|
e02642cf3b | ||
|
|
b60f08e782 | ||
|
|
4fc331f8e8 | ||
|
|
507f2f950d | ||
|
|
1c935a3445 | ||
|
|
dfae365f84 | ||
|
|
5ca5e475bb | ||
|
|
3ba75f1300 | ||
|
|
a7ff759ca1 | ||
|
|
d2c31f429b | ||
|
|
cb5da59226 | ||
|
|
2f33980a91 | ||
|
|
e189c31375 | ||
|
|
1eae55984d | ||
|
|
244df24bf4 | ||
|
|
28b9f1e68b | ||
|
|
0c8eccc3fc | ||
|
|
7b84d5b0ec | ||
|
|
6600954906 | ||
|
|
4a65e10f5e | ||
|
|
d4eb276eea | ||
|
|
91a7e49846 | ||
|
|
dfb206c8b0 | ||
|
|
9581e3df0c | ||
|
|
964f79f7c8 | ||
|
|
460accf9be | ||
|
|
780b40ea7b | ||
|
|
e613fdd83c | ||
|
|
62c2374a8c | ||
|
|
84525b26fe | ||
|
|
be2ddacb90 | ||
|
|
42cc412c4a | ||
|
|
f1b4c76648 | ||
|
|
ee206367d4 | ||
|
|
2638237e1f | ||
|
|
67063ead60 | ||
|
|
a3b7dfcfca | ||
|
|
bcbaf671a9 | ||
|
|
c58cd28279 | ||
|
|
f328457cb1 | ||
|
|
7b5a21deaa | ||
|
|
895a1c03be | ||
|
|
679d679f25 | ||
|
|
0235e150e2 | ||
|
|
17ea56ee73 | ||
|
|
b4440f5aa2 | ||
|
|
fe7ee4a624 | ||
|
|
a40058dbd1 | ||
|
|
c70cc5832b | ||
|
|
a4ba1bd73e | ||
|
|
61e0bbda6b | ||
|
|
a38c4dfa99 | ||
|
|
975f685d69 | ||
|
|
4155405e60 | ||
|
|
55b5d88b01 | ||
|
|
2f110a50df | ||
|
|
7fd7e8264f | ||
|
|
1279a20c03 | ||
|
|
39f9189f34 | ||
|
|
434eb4b0ac | ||
|
|
5ee455ffc2 | ||
|
|
e972c6705f | ||
|
|
12b8c116a4 | ||
|
|
e9d91fccfc | ||
|
|
d5cfb89959 | ||
|
|
a3de1384c3 | ||
|
|
abf77a9eda | ||
|
|
75d9411e80 | ||
|
|
cc000cfb5e | ||
|
|
e1143f1265 | ||
|
|
244e0e2059 | ||
|
|
1a91508857 | ||
|
|
a138041c59 | ||
|
|
c17bd99f1c | ||
|
|
5102b2c093 | ||
|
|
2c6858a018 | ||
|
|
8ddffeeea3 | ||
|
|
238ba3b625 | ||
|
|
988d225cf0 | ||
|
|
a737255791 | ||
|
|
64669fdd8d | ||
|
|
e141586053 | ||
|
|
6f69654294 | ||
|
|
3706c4f855 | ||
|
|
96637d032f | ||
|
|
3300502231 | ||
|
|
8975c05d19 | ||
|
|
07949ce2ae | ||
|
|
dff3f8ccab | ||
|
|
8a1f378f05 | ||
|
|
ec5130c3f9 | ||
|
|
a7b16bfb33 | ||
|
|
2b4b293ebb | ||
|
|
c880de3004 | ||
|
|
c83b9bd9c6 | ||
|
|
e900006642 | ||
|
|
357d28a256 | ||
|
|
1de43a1a17 | ||
|
|
821b0ba8cb | ||
|
|
acfe668ecb | ||
|
|
73b0c1f947 | ||
|
|
3e7d2a6492 | ||
|
|
cd1a510d16 | ||
|
|
9a5a5140e5 | ||
|
|
f610339f74 | ||
|
|
71a782b641 | ||
|
|
cdbba74d7a | ||
|
|
81264cfcaf | ||
|
|
c798dd7ae5 | ||
|
|
b00d1bd225 | ||
|
|
47effc4bd3 | ||
|
|
d651403b47 | ||
|
|
48c90d3781 | ||
|
|
d59b2905f9 | ||
|
|
0f478a7de7 | ||
|
|
9d898acc56 | ||
|
|
a855c74183 | ||
|
|
fb76f210eb | ||
|
|
97dcdb1926 | ||
|
|
7bccb562e4 | ||
|
|
4db0a9a6b7 | ||
|
|
850f002cb2 | ||
|
|
df0ac426f3 | ||
|
|
6c692ad1cb | ||
|
|
ac5180e29c | ||
|
|
fb85db1d3e | ||
|
|
06948c6ee5 | ||
|
|
495ffca2c2 | ||
|
|
e81cc74ca2 | ||
|
|
57a9a7196f | ||
|
|
0c1fa696aa | ||
|
|
ee970e38a6 | ||
|
|
f5e4d85cd2 | ||
|
|
47e95602c4 | ||
|
|
c4d73c306b | ||
|
|
6999994def | ||
|
|
f1635257cb | ||
|
|
7ca20a2679 | ||
|
|
3136561cd0 | ||
|
|
1a91b51976 | ||
|
|
2108309302 | ||
|
|
27eec099d6 | ||
|
|
e3aaff185f | ||
|
|
0b1c752b5c | ||
|
|
8bcd689c04 | ||
|
|
d938c104e1 | ||
|
|
524c5ed87d | ||
|
|
75ad046bfb | ||
|
|
77c8e993ec | ||
|
|
51dcac5da7 | ||
|
|
99ab53e998 | ||
|
|
730e07e2f7 | ||
|
|
1b8cc56194 | ||
|
|
ee3718dd71 | ||
|
|
ec67735412 | ||
|
|
7825bfb49d | ||
|
|
03a698b9c6 | ||
|
|
e0680d3061 | ||
|
|
4e63e48879 | ||
|
|
a302ad427d | ||
|
|
9e59aa1bc8 | ||
|
|
7c9b3938df | ||
|
|
6dfcdb9878 | ||
|
|
6d9275e412 | ||
|
|
571f898192 | ||
|
|
07c4cacb58 | ||
|
|
612c28b89f | ||
|
|
b51e940dfa | ||
|
|
a78671543b | ||
|
|
69ebb2d720 | ||
|
|
1fe609ea05 | ||
|
|
7233c428ec | ||
|
|
223e526f27 | ||
|
|
e6c67bf803 | ||
|
|
2a31fe8552 | ||
|
|
9f2ed35da0 | ||
|
|
264f16dcf6 | ||
|
|
abf201a894 | ||
|
|
e64ec13c13 | ||
|
|
8528c622b0 | ||
|
|
93309c6dbf | ||
|
|
a6ba1d709e | ||
|
|
4d8af0c945 | ||
|
|
0b23a1ee7e | ||
|
|
ff8290179c | ||
|
|
c1128f3db3 | ||
|
|
739e441d4d | ||
|
|
442e471cfc | ||
|
|
bc9cd56345 | ||
|
|
08fe5aabff | ||
|
|
5ec89b8c50 | ||
|
|
df63ee1a1d | ||
|
|
ee2668e586 | ||
|
|
e8b7eb6908 | ||
|
|
bae2992cb0 | ||
|
|
3c569c00df | ||
|
|
4296fec7f5 | ||
|
|
761de533b2 | ||
|
|
8367fc2aac | ||
|
|
d2bff50845 | ||
|
|
20a2b1c341 | ||
|
|
538d718ff4 | ||
|
|
c8583bbdf1 | ||
|
|
8e67d8b364 | ||
|
|
6ac063d10e | ||
|
|
fd34b17f90 | ||
|
|
60fbcad9ac | ||
|
|
f250c6c73e | ||
|
|
c40f8cb9f8 | ||
|
|
83efa3dd71 | ||
|
|
56e279021f | ||
|
|
993e9ebd07 | ||
|
|
7ae0c9543d | ||
|
|
f3e0bffcb1 | ||
|
|
c2a345fa67 | ||
|
|
e0a5f58d2c | ||
|
|
2bc22c40eb | ||
|
|
d54c92e3e6 | ||
|
|
d41a9a07e4 | ||
|
|
cc7dbaa3a1 | ||
|
|
3b2c25d223 | ||
|
|
0209466496 | ||
|
|
722d003076 | ||
|
|
df78de04e4 | ||
|
|
912bb8c577 | ||
|
|
8ec1732af0 | ||
|
|
636cb8633b | ||
|
|
04a35efe69 | ||
|
|
cf7f70c25d | ||
|
|
d0e500c876 | ||
|
|
939a05633f | ||
|
|
7a68f5ab4b | ||
|
|
50c1d00839 | ||
|
|
de24da8c11 | ||
|
|
038086dc08 | ||
|
|
953f901dd2 | ||
|
|
870828c8af | ||
|
|
930af43437 | ||
|
|
cdced3a3ad | ||
|
|
125da33f82 | ||
|
|
e89abc80ea | ||
|
|
d9e90857f0 | ||
|
|
bb0b4bb783 | ||
|
|
e43eb667b5 | ||
|
|
b5fa965bcb | ||
|
|
d5ed7f1256 | ||
|
|
e9cb18484e | ||
|
|
2fbfa0358b | ||
|
|
c8cbdbd2c4 | ||
|
|
3a7b95593a | ||
|
|
a3e02e5e4a | ||
|
|
2e42847f4e | ||
|
|
abb109f30f | ||
|
|
bb6248bca4 | ||
|
|
2c31ecb8fa |
7
.github/dependabot.yml
vendored
Normal file
7
.github/dependabot.yml
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/" # Location of package manifests
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
23
.github/stale.yml
vendored
23
.github/stale.yml
vendored
@ -1,23 +0,0 @@
|
||||
# Number of days of inactivity before an issue becomes stale
|
||||
daysUntilStale: 28
|
||||
# Number of days of inactivity before a stale issue is closed
|
||||
# Set to false to disable. If disabled, issues still need to be closed
|
||||
# manually, but will remain marked as stale.
|
||||
daysUntilClose: false
|
||||
# Issues with these labels will never be considered stale
|
||||
exemptLabels:
|
||||
- v2
|
||||
- enhancement
|
||||
- good first issue
|
||||
- feature-request
|
||||
- doc
|
||||
- bug
|
||||
- not-stale
|
||||
# Label to use when marking an issue as stale
|
||||
staleLabel: stale
|
||||
# Comment to post when marking an issue as stale. Set to `false` to disable
|
||||
markComment: >
|
||||
This issue has been automatically marked as stale because it has not had
|
||||
recent activity. Thank you for your contributions.
|
||||
# Comment to post when closing a stale issue. Set to `false` to disable
|
||||
closeComment: false
|
||||
25
.github/workflows/CI-docs.yml
vendored
Normal file
25
.github/workflows/CI-docs.yml
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
name: CI-docs
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'docs/**'
|
||||
- '!docs/code/**'
|
||||
- '.github/workflows/CI-docs.yml'
|
||||
|
||||
jobs:
|
||||
docs-src:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.9'
|
||||
cache: 'pip' # caching pip dependencies
|
||||
- run: pip install -r docs/requirements.txt
|
||||
- name: html
|
||||
run: |
|
||||
make -C docs html
|
||||
- name: linkcheck
|
||||
run: |
|
||||
make -C docs linkcheck
|
||||
33
.github/workflows/CI-sample.yml
vendored
Normal file
33
.github/workflows/CI-sample.yml
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
name: ci-sample
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- '**'
|
||||
- '!docs/**'
|
||||
- '!.**'
|
||||
- 'docs/code/**'
|
||||
- '.github/workflows/CI-sample.yml'
|
||||
push:
|
||||
branches:
|
||||
- v[0-9].*
|
||||
- master
|
||||
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [macos-latest, ubuntu-latest, windows-latest]
|
||||
runs-on: ${{matrix.os}}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: setup
|
||||
run: cmake -E make_directory ${{runner.workspace}}/libuv/docs/code/build
|
||||
- name: configure
|
||||
# you may like use Ninja on unix-like OS, but for windows, the only easy way is to use Visual Studio if you want Ninja
|
||||
run: cmake ..
|
||||
working-directory: ${{runner.workspace}}/libuv/docs/code/build
|
||||
- name: build
|
||||
run: cmake --build .
|
||||
working-directory: ${{runner.workspace}}/libuv/docs/code/build
|
||||
182
.github/workflows/CI-unix.yml
vendored
Normal file
182
.github/workflows/CI-unix.yml
vendored
Normal file
@ -0,0 +1,182 @@
|
||||
name: CI-unix
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- '**'
|
||||
- '!docs/**'
|
||||
- '!src/win/**'
|
||||
- '!.**'
|
||||
- '.github/workflows/CI-unix.yml'
|
||||
push:
|
||||
branches:
|
||||
- v[0-9].*
|
||||
- master
|
||||
|
||||
jobs:
|
||||
build-linux:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: configure
|
||||
run: |
|
||||
./autogen.sh
|
||||
mkdir build
|
||||
(cd build && ../configure)
|
||||
- name: distcheck
|
||||
run: |
|
||||
make -C build distcheck
|
||||
|
||||
build-android:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
ANDROID_AVD_HOME: /root/.android/avd
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Envinfo
|
||||
run: npx envinfo
|
||||
- name: Enable KVM
|
||||
run: |
|
||||
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
|
||||
sudo udevadm control --reload-rules
|
||||
sudo udevadm trigger --name-match=kvm
|
||||
- name: Build and Test
|
||||
uses: reactivecircus/android-emulator-runner@v2
|
||||
with:
|
||||
api-level: 30
|
||||
arch: x86_64
|
||||
target: google_apis
|
||||
ram-size: 2048M
|
||||
emulator-options: -no-audio -no-window -gpu off -no-boot-anim -netdelay none -netspeed full -writable-system -no-snapshot-save -no-snapshot-load -no-snapshot
|
||||
disable-animations: true
|
||||
script: |
|
||||
echo "::group::Configure"
|
||||
cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake -DCMAKE_BUILD_TYPE=Release -DANDROID_ABI="x86_64" -DANDROID_PLATFORM=android-30
|
||||
echo "::endgroup::"
|
||||
|
||||
echo "::group::Build"
|
||||
cmake --build build
|
||||
|
||||
## Correct some ld bugs that cause problems with libuv tests
|
||||
wget "https://github.com/termux/termux-elf-cleaner/releases/download/v2.2.1/termux-elf-cleaner" -P build
|
||||
chmod a+x build/termux-elf-cleaner
|
||||
build/termux-elf-cleaner --api-level 30 ./build/uv_run_tests
|
||||
build/termux-elf-cleaner --api-level 30 ./build/uv_run_tests_a
|
||||
|
||||
adb shell "su 0 setenforce 0" # to allow some syscalls like link, chmod, etc.
|
||||
|
||||
## Push the build and test fixtures to the device
|
||||
adb push build /data/local/tmp
|
||||
adb shell mkdir /data/local/tmp/build/test
|
||||
adb push test/fixtures /data/local/tmp/build/test
|
||||
echo "::endgroup::"
|
||||
|
||||
## Run the tests
|
||||
file build/uv_run_tests_a
|
||||
adb shell "cd /data/local/tmp/build && env UV_TEST_TIMEOUT_MULTIPLIER=5 ./uv_run_tests_a"
|
||||
|
||||
build-macos:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [macos-13, macos-14]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Envinfo
|
||||
run: npx envinfo
|
||||
- name: Disable Firewall
|
||||
run: |
|
||||
/usr/libexec/ApplicationFirewall/socketfilterfw --getglobalstate
|
||||
sudo defaults write /Library/Preferences/com.apple.alf globalstate -int 0
|
||||
/usr/libexec/ApplicationFirewall/socketfilterfw --getglobalstate
|
||||
- name: Setup
|
||||
run: |
|
||||
brew install ninja automake libtool
|
||||
- name: Configure
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DBUILD_TESTING=ON -G Ninja
|
||||
- name: Build
|
||||
run: |
|
||||
cmake --build build
|
||||
ls -lh
|
||||
- name: platform_output
|
||||
run: |
|
||||
./build/uv_run_tests platform_output
|
||||
- name: platform_output_a
|
||||
run: |
|
||||
./build/uv_run_tests_a platform_output
|
||||
- name: Test
|
||||
run: |
|
||||
cd build && ctest -V
|
||||
- name: Autotools configure
|
||||
if: always()
|
||||
run: |
|
||||
./autogen.sh
|
||||
mkdir build-auto
|
||||
(cd build-auto && ../configure)
|
||||
make -C build-auto -j4
|
||||
|
||||
build-ios:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [macos-13, macos-14]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Configure
|
||||
run: |
|
||||
mkdir build-ios
|
||||
cd build-ios
|
||||
cmake .. -GXcode -DCMAKE_SYSTEM_NAME:STRING=iOS -DCMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED:BOOL=NO -DCMAKE_CONFIGURATION_TYPES:STRING=Release
|
||||
- name: Build
|
||||
run: |
|
||||
cmake --build build-ios
|
||||
ls -lh build-ios
|
||||
|
||||
build-cross-qemu:
|
||||
runs-on: ubuntu-24.04
|
||||
name: build-cross-qemu-${{ matrix.config.target }}
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
config:
|
||||
- {target: arm, toolchain: gcc-arm-linux-gnueabi, cc: arm-linux-gnueabi-gcc, qemu: qemu-arm }
|
||||
- {target: armhf, toolchain: gcc-arm-linux-gnueabihf, cc: arm-linux-gnueabihf-gcc, qemu: qemu-arm }
|
||||
- {target: aarch64, toolchain: gcc-aarch64-linux-gnu, cc: aarch64-linux-gnu-gcc, qemu: qemu-aarch64 }
|
||||
- {target: riscv64, toolchain: gcc-riscv64-linux-gnu, cc: riscv64-linux-gnu-gcc, qemu: qemu-riscv64 }
|
||||
- {target: ppc, toolchain: gcc-powerpc-linux-gnu, cc: powerpc-linux-gnu-gcc, qemu: qemu-ppc }
|
||||
- {target: ppc64, toolchain: gcc-powerpc64-linux-gnu, cc: powerpc64-linux-gnu-gcc, qemu: qemu-ppc64 }
|
||||
- {target: ppc64le, toolchain: gcc-powerpc64le-linux-gnu, cc: powerpc64le-linux-gnu-gcc, qemu: qemu-ppc64le }
|
||||
- {target: s390x, toolchain: gcc-s390x-linux-gnu, cc: s390x-linux-gnu-gcc, qemu: qemu-s390x }
|
||||
- {target: mips, toolchain: gcc-mips-linux-gnu, cc: mips-linux-gnu-gcc, qemu: qemu-mips }
|
||||
- {target: mips64, toolchain: gcc-mips64-linux-gnuabi64, cc: mips64-linux-gnuabi64-gcc, qemu: qemu-mips64 }
|
||||
- {target: mipsel, toolchain: gcc-mipsel-linux-gnu, cc: mipsel-linux-gnu-gcc, qemu: qemu-mipsel }
|
||||
- {target: mips64el, toolchain: gcc-mips64el-linux-gnuabi64, cc: mips64el-linux-gnuabi64-gcc,qemu: qemu-mips64el }
|
||||
- {target: arm (u64 slots), toolchain: gcc-arm-linux-gnueabi, cc: arm-linux-gnueabi-gcc, qemu: qemu-arm }
|
||||
- {target: aarch64 (u64 slots), toolchain: gcc-aarch64-linux-gnu, cc: aarch64-linux-gnu-gcc, qemu: qemu-aarch64 }
|
||||
- {target: ppc (u64 slots), toolchain: gcc-powerpc-linux-gnu, cc: powerpc-linux-gnu-gcc, qemu: qemu-ppc }
|
||||
- {target: ppc64 (u64 slots), toolchain: gcc-powerpc64-linux-gnu, cc: powerpc64-linux-gnu-gcc, qemu: qemu-ppc64 }
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install qemu and ${{ matrix.config.toolchain }}
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo apt install qemu-user qemu-user-binfmt ${{ matrix.config.toolchain }} -y
|
||||
- name: Configure with ${{ matrix.config.cc }}
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DBUILD_TESTING=ON -DQEMU=ON -DCMAKE_C_COMPILER=${{ matrix.config.cc }}
|
||||
- name: Build
|
||||
run: |
|
||||
cmake --build build
|
||||
ls -lh build
|
||||
- name: Test
|
||||
run: |
|
||||
${{ matrix.config.qemu }} build/uv_run_tests_a
|
||||
129
.github/workflows/CI-win.yml
vendored
Normal file
129
.github/workflows/CI-win.yml
vendored
Normal file
@ -0,0 +1,129 @@
|
||||
name: CI-win
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- '**'
|
||||
- '!docs/**'
|
||||
- '!src/unix/**'
|
||||
- '!.**'
|
||||
- '.github/workflows/CI-win.yml'
|
||||
push:
|
||||
branches:
|
||||
- v[0-9].*
|
||||
- master
|
||||
|
||||
jobs:
|
||||
build-windows:
|
||||
runs-on: windows-${{ matrix.config.server }}
|
||||
name: build-${{ join(matrix.config.*, '-') }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
config:
|
||||
- {toolchain: Visual Studio 16 2019, arch: Win32, server: 2019}
|
||||
- {toolchain: Visual Studio 16 2019, arch: x64, server: 2019}
|
||||
- {toolchain: Visual Studio 17 2022, arch: Win32, server: 2022}
|
||||
- {toolchain: Visual Studio 17 2022, arch: x64, server: 2022}
|
||||
- {toolchain: Visual Studio 17 2022, arch: x64, server: 2022, config: ASAN}
|
||||
- {toolchain: Visual Studio 17 2022, arch: x64, server: 2022, config: UBSAN}
|
||||
- {toolchain: Visual Studio 17 2022, arch: arm64, server: 2022}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Build
|
||||
run:
|
||||
cmake -S . -B build -DBUILD_TESTING=ON
|
||||
-G "${{ matrix.config.toolchain }}" -A ${{ matrix.config.arch }}
|
||||
${{ matrix.config.config == 'ASAN' && '-DASAN=on -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded' || '' }}
|
||||
|
||||
cmake --build build --config RelWithDebInfo
|
||||
|
||||
${{ matrix.config.config == 'ASAN' && 'Copy-Item -Path "build\\*.exe" -Destination "build\\RelWithDebInfo\\"' || '' }}
|
||||
|
||||
${{ matrix.config.config == 'ASAN' && 'Copy-Item -Path "build\\*.dll" -Destination "build\\RelWithDebInfo\\"' || '' }}
|
||||
|
||||
ls -l build
|
||||
|
||||
ls -l build\\RelWithDebInfo
|
||||
- name: platform_output_a
|
||||
if: ${{ matrix.config.arch != 'arm64' }}
|
||||
shell: cmd
|
||||
run:
|
||||
build\\RelWithDebInfo\\uv_run_tests_a.exe platform_output
|
||||
- name: platform_output
|
||||
if: ${{ matrix.config.arch != 'arm64' }}
|
||||
shell: cmd
|
||||
run:
|
||||
build\\RelWithDebInfo\\uv_run_tests.exe platform_output
|
||||
- name: Test
|
||||
# only valid with libuv-master with the fix for
|
||||
# https://github.com/libuv/leps/blob/master/005-windows-handles-not-fd.md
|
||||
if: ${{ matrix.config.config != 'ASAN' && matrix.config.arch != 'arm64' }}
|
||||
shell: cmd
|
||||
run:
|
||||
cd build
|
||||
|
||||
ctest -C RelWithDebInfo -V
|
||||
- name: Test only static
|
||||
if: ${{ matrix.config.config == 'ASAN' && matrix.config.arch != 'arm64' }}
|
||||
shell: cmd
|
||||
run:
|
||||
build\\RelWithDebInfo\\uv_run_tests_a.exe
|
||||
|
||||
build-mingw:
|
||||
runs-on: ubuntu-latest
|
||||
name: build-mingw-${{ matrix.config.arch }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
config:
|
||||
- {arch: i686, server: 2022, libgcc: dw2 }
|
||||
- {arch: x86_64, server: 2022, libgcc: seh }
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install mingw32 environment
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo apt install mingw-w64 ninja-build -y
|
||||
- name: Build
|
||||
run: |
|
||||
cmake -S . -B build -G Ninja -DHOST_ARCH=${{ matrix.config.arch }} -DBUILD_TESTING=ON -DCMAKE_TOOLCHAIN_FILE=cmake-toolchains/cross-mingw32.cmake
|
||||
cmake --build build
|
||||
cmake --install build --prefix "`pwd`/build/usr"
|
||||
mkdir -p build/usr/test build/usr/bin
|
||||
cp -av test/fixtures build/usr/test
|
||||
cp -av build/uv_run_tests_a.exe build/uv_run_tests.exe build/uv_run_tests_a_no_ext build/uv_run_tests_no_ext \
|
||||
`${{ matrix.config.arch }}-w64-mingw32-gcc -print-file-name=libgcc_s_${{ matrix.config.libgcc }}-1.dll` \
|
||||
`${{ matrix.config.arch }}-w64-mingw32-gcc -print-file-name=libwinpthread-1.dll` \
|
||||
`${{ matrix.config.arch }}-w64-mingw32-gcc -print-file-name=libatomic-1.dll` \
|
||||
build/usr/bin
|
||||
- name: Upload build artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: mingw-${{ matrix.config.arch }}
|
||||
path: build/usr/**/*
|
||||
retention-days: 2
|
||||
|
||||
test-mingw:
|
||||
runs-on: windows-${{ matrix.config.server }}
|
||||
name: test-mingw-${{ matrix.config.arch }}
|
||||
needs: build-mingw
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
config:
|
||||
- {arch: i686, server: 2022}
|
||||
- {arch: x86_64, server: 2022}
|
||||
steps:
|
||||
- name: Download build artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: mingw-${{ matrix.config.arch }}
|
||||
- name: Test
|
||||
shell: cmd
|
||||
run: |
|
||||
bin\uv_run_tests_a.exe
|
||||
- name: Test
|
||||
shell: cmd
|
||||
run: |
|
||||
bin\uv_run_tests.exe
|
||||
118
.github/workflows/CI.yml
vendored
118
.github/workflows/CI.yml
vendored
@ -1,118 +0,0 @@
|
||||
name: CI
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build-windows:
|
||||
runs-on: windows-${{ matrix.config.server }}
|
||||
name: build-${{ matrix.config.toolchain}}-${{ matrix.config.arch}}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
config:
|
||||
- {toolchain: Visual Studio 15 2017, arch: Win32, server: 2016}
|
||||
- {toolchain: Visual Studio 15 2017, arch: x64, server: 2016}
|
||||
- {toolchain: Visual Studio 16 2019, arch: Win32, server: 2019}
|
||||
- {toolchain: Visual Studio 16 2019, arch: x64, server: 2019}
|
||||
- {toolchain: Visual Studio 17 2022, arch: Win32, server: 2022}
|
||||
- {toolchain: Visual Studio 17 2022, arch: x64, server: 2022}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Envinfo
|
||||
run: npx envinfo
|
||||
- name: Build
|
||||
shell: cmd
|
||||
run: |
|
||||
mkdir -p build
|
||||
cd build
|
||||
cmake .. -DBUILD_TESTING=ON -G "${{ matrix.config.toolchain }}" -A ${{ matrix.config.arch }}
|
||||
cmake --build .
|
||||
- name: Test
|
||||
shell: cmd
|
||||
run: |
|
||||
cd build
|
||||
ctest -C Debug --output-on-failure
|
||||
|
||||
build-android:
|
||||
runs-on: ubuntu-latest
|
||||
container: reactnativecommunity/react-native-android:2020-5-20
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Envinfo
|
||||
run: npx envinfo
|
||||
- name: Build android arm64
|
||||
# see build options you can use in https://developer.android.com/ndk/guides/cmake
|
||||
run: |
|
||||
mkdir build && cd build
|
||||
$ANDROID_HOME/cmake/3.10.2.4988404/bin/cmake -DCMAKE_TOOLCHAIN_FILE=$ANDROID_HOME/ndk/20.0.5594570/build/cmake/android.toolchain.cmake -DCMAKE_BUILD_TYPE=Release -DANDROID_ABI="arm64-v8a" -DANDROID_PLATFORM=android-21 ..
|
||||
$ANDROID_HOME/cmake/3.10.2.4988404/bin/cmake --build .
|
||||
|
||||
build-macos:
|
||||
runs-on: macos-10.15
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Envinfo
|
||||
run: npx envinfo
|
||||
- name: Setup
|
||||
run: |
|
||||
brew install ninja
|
||||
- name: Build
|
||||
run: |
|
||||
mkdir build
|
||||
cd build && cmake .. -DBUILD_TESTING=ON -G Ninja
|
||||
cmake --build .
|
||||
ls -lh
|
||||
- name: Test
|
||||
run: |
|
||||
cd build && ctest -V
|
||||
|
||||
build-cross-qemu:
|
||||
runs-on: ubuntu-latest
|
||||
name: build-cross-qemu-${{ matrix.config.target }}
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
config:
|
||||
- {target: arm, toolchain: gcc-arm-linux-gnueabi, cc: arm-linux-gnueabi-gcc, qemu: qemu-arm-static }
|
||||
- {target: armhf, toolchain: gcc-arm-linux-gnueabihf, cc: arm-linux-gnueabihf-gcc, qemu: qemu-arm-static }
|
||||
- {target: aarch64, toolchain: gcc-aarch64-linux-gnu, cc: aarch64-linux-gnu-gcc, qemu: qemu-aarch64-static }
|
||||
- {target: riscv64, toolchain: gcc-riscv64-linux-gnu, cc: riscv64-linux-gnu-gcc, qemu: qemu-riscv64-static }
|
||||
- {target: ppc, toolchain: gcc-powerpc-linux-gnu, cc: powerpc-linux-gnu-gcc, qemu: qemu-ppc-static }
|
||||
- {target: ppc64, toolchain: gcc-powerpc64-linux-gnu, cc: powerpc64-linux-gnu-gcc, qemu: qemu-ppc64-static }
|
||||
- {target: ppc64le, toolchain: gcc-powerpc64le-linux-gnu, cc: powerpc64le-linux-gnu-gcc, qemu: qemu-ppc64le-static }
|
||||
- {target: s390x, toolchain: gcc-s390x-linux-gnu, cc: s390x-linux-gnu-gcc, qemu: qemu-s390x-static }
|
||||
- {target: mips, toolchain: gcc-mips-linux-gnu, cc: mips-linux-gnu-gcc, qemu: qemu-mips-static }
|
||||
- {target: mips64, toolchain: gcc-mips64-linux-gnuabi64, cc: mips64-linux-gnuabi64-gcc, qemu: qemu-mips64-static }
|
||||
- {target: mipsel, toolchain: gcc-mipsel-linux-gnu, cc: mipsel-linux-gnu-gcc, qemu: qemu-mipsel-static }
|
||||
- {target: mips64el,toolchain: gcc-mips64el-linux-gnuabi64, cc: mips64el-linux-gnuabi64-gcc,qemu: qemu-mips64el-static }
|
||||
- {target: alpha, toolchain: gcc-alpha-linux-gnu, cc: alpha-linux-gnu-gcc, qemu: qemu-alpha-static }
|
||||
- {target: arm (u64 slots), toolchain: gcc-arm-linux-gnueabi, cc: arm-linux-gnueabi-gcc, qemu: qemu-arm-static}
|
||||
- {target: aarch64 (u64 slots), toolchain: gcc-aarch64-linux-gnu, cc: aarch64-linux-gnu-gcc, qemu: qemu-aarch64-static}
|
||||
- {target: ppc (u64 slots), toolchain: gcc-powerpc-linux-gnu, cc: powerpc-linux-gnu-gcc, qemu: qemu-ppc-static}
|
||||
- {target: ppc64 (u64 slots), toolchain: gcc-powerpc64-linux-gnu, cc: powerpc64-linux-gnu-gcc, qemu: qemu-ppc64-static}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Install QEMU
|
||||
# this ensure install latest qemu on ubuntu, apt get version is old
|
||||
env:
|
||||
QEMU_SRC: "http://archive.ubuntu.com/ubuntu/pool/universe/q/qemu"
|
||||
QEMU_VER: "qemu-user-static_4\\.2-.*_amd64.deb$"
|
||||
run: |
|
||||
DEB=`curl -s $QEMU_SRC/ | grep -o -E 'href="([^"#]+)"' | cut -d'"' -f2 | grep $QEMU_VER | tail -1`
|
||||
wget $QEMU_SRC/$DEB
|
||||
sudo dpkg -i $DEB
|
||||
- name: Install ${{ matrix.config.toolchain }}
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo apt install ${{ matrix.config.toolchain }} -y
|
||||
- name: Build
|
||||
run: |
|
||||
mkdir build
|
||||
cd build && cmake .. -DBUILD_TESTING=ON -DQEMU=ON -DCMAKE_C_COMPILER=${{ matrix.config.cc }}
|
||||
cmake --build .
|
||||
ls -lh
|
||||
- name: Test
|
||||
run: |
|
||||
${{ matrix.config.qemu }} build/uv_run_tests_a
|
||||
122
.github/workflows/sanitizer.yml
vendored
122
.github/workflows/sanitizer.yml
vendored
@ -1,26 +1,128 @@
|
||||
name: Sanitizer checks
|
||||
|
||||
on: [push, pull_request]
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- '**'
|
||||
- '!docs/**'
|
||||
- '!.**'
|
||||
- '.github/workflows/sanitizer.yml'
|
||||
push:
|
||||
branches:
|
||||
- v[0-9].*
|
||||
- master
|
||||
|
||||
jobs:
|
||||
sanitizers:
|
||||
runs-on: ubuntu-latest
|
||||
sanitizers-linux:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup
|
||||
run: |
|
||||
sudo apt-get install ninja-build
|
||||
- name: Envinfo
|
||||
run: npx envinfo
|
||||
- name: TSAN
|
||||
|
||||
# [AM]SAN fail on newer kernels due to a bigger PIE slide
|
||||
- name: Disable ASLR
|
||||
run: |
|
||||
mkdir build-tsan
|
||||
(cd build-tsan && cmake .. -G Ninja -DBUILD_TESTING=ON -DTSAN=ON -DCMAKE_BUILD_TYPE=Release)
|
||||
cmake --build build-tsan
|
||||
./build-tsan/uv_run_tests_a || true # currently permit failures
|
||||
- name: ASAN
|
||||
sudo sysctl -w kernel.randomize_va_space=0
|
||||
|
||||
- name: ASAN Build
|
||||
run: |
|
||||
mkdir build-asan
|
||||
(cd build-asan && cmake .. -G Ninja -DBUILD_TESTING=ON -DASAN=ON -DCMAKE_BUILD_TYPE=Debug)
|
||||
cmake --build build-asan
|
||||
- name: ASAN Test
|
||||
run: |
|
||||
./build-asan/uv_run_tests_a
|
||||
|
||||
- name: MSAN Build
|
||||
run: |
|
||||
mkdir build-msan
|
||||
(cd build-msan && cmake .. -G Ninja -DBUILD_TESTING=ON -DMSAN=ON -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_COMPILER=clang)
|
||||
cmake --build build-msan
|
||||
- name: MSAN Test
|
||||
run: |
|
||||
./build-msan/uv_run_tests_a
|
||||
|
||||
- name: TSAN Build
|
||||
run: |
|
||||
mkdir build-tsan
|
||||
(cd build-tsan && cmake .. -G Ninja -DBUILD_TESTING=ON -DTSAN=ON -DCMAKE_BUILD_TYPE=Release)
|
||||
cmake --build build-tsan
|
||||
- name: TSAN Test
|
||||
# Note: path must be absolute because some tests chdir.
|
||||
# TSan exits with an error when it can't find the file.
|
||||
run: |
|
||||
env TSAN_OPTIONS="suppressions=$PWD/tsansupp.txt" ./build-tsan/uv_run_tests_a
|
||||
|
||||
- name: UBSAN Build
|
||||
run: |
|
||||
mkdir build-ubsan
|
||||
(cd build-ubsan && cmake .. -G Ninja -DBUILD_TESTING=ON -DUBSAN=ON -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_COMPILER=clang)
|
||||
cmake --build build-ubsan
|
||||
- name: UBSAN Test
|
||||
run: |
|
||||
./build-ubsan/uv_run_tests_a
|
||||
|
||||
sanitizers-macos:
|
||||
runs-on: macos-13
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Envinfo
|
||||
run: npx envinfo
|
||||
|
||||
- name: ASAN Build
|
||||
run: |
|
||||
mkdir build-asan
|
||||
(cd build-asan && cmake .. -DBUILD_TESTING=ON -DASAN=ON -DCMAKE_BUILD_TYPE=Debug)
|
||||
cmake --build build-asan
|
||||
- name: ASAN Test
|
||||
run: |
|
||||
./build-asan/uv_run_tests_a
|
||||
|
||||
- name: TSAN Build
|
||||
run: |
|
||||
mkdir build-tsan
|
||||
(cd build-tsan && cmake .. -DBUILD_TESTING=ON -DTSAN=ON -DCMAKE_BUILD_TYPE=Release)
|
||||
cmake --build build-tsan
|
||||
- name: TSAN Test
|
||||
run: |
|
||||
./build-tsan/uv_run_tests_a
|
||||
|
||||
- name: UBSAN Build
|
||||
run: |
|
||||
mkdir build-ubsan
|
||||
(cd build-ubsan && cmake .. -DBUILD_TESTING=ON -DUBSAN=ON -DCMAKE_BUILD_TYPE=Debug)
|
||||
cmake --build build-ubsan
|
||||
- name: UBSAN Test
|
||||
run: |
|
||||
./build-ubsan/uv_run_tests_a
|
||||
|
||||
sanitizers-windows:
|
||||
runs-on: windows-2022
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup
|
||||
run: |
|
||||
choco install ninja
|
||||
|
||||
# Note: clang shipped with VS2022 has an issue where the UBSAN runtime doesn't link.
|
||||
- name: Install LLVM and Clang
|
||||
uses: KyleMayes/install-llvm-action@v2
|
||||
with:
|
||||
version: "17"
|
||||
|
||||
- name: Envinfo
|
||||
run: npx envinfo
|
||||
|
||||
- name: UBSAN Build
|
||||
run: |
|
||||
mkdir build-ubsan
|
||||
cmake -B build-ubsan -G Ninja -DBUILD_TESTING=ON -DUBSAN=ON -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_COMPILER=clang
|
||||
cmake --build build-ubsan
|
||||
- name: UBSAN Test
|
||||
run: |
|
||||
./build-ubsan/uv_run_tests_a
|
||||
|
||||
4
.gitignore
vendored
4
.gitignore
vendored
@ -7,9 +7,11 @@
|
||||
*.sdf
|
||||
*.suo
|
||||
.vs/
|
||||
.vscode/
|
||||
*.VC.db
|
||||
*.VC.opendb
|
||||
core
|
||||
.cache
|
||||
vgcore.*
|
||||
.buildstamp
|
||||
.dirstamp
|
||||
@ -74,3 +76,5 @@ cmake-build-debug/
|
||||
|
||||
# make dist output
|
||||
libuv-*.tar.*
|
||||
/dist.libuv.org/
|
||||
/libuv-release-tool/
|
||||
|
||||
9
.mailmap
9
.mailmap
@ -4,6 +4,7 @@ Aaron Bieber <qbit@deftly.net> <deftly@gmail.com>
|
||||
Alan Gutierrez <alan@prettyrobots.com> <alan@blogometer.com>
|
||||
Andrius Bentkus <andrius.bentkus@gmail.com> <toxedvirus@gmail.com>
|
||||
Andy Fiddaman <andy@omniosce.org> <omnios@citrus-it.co.uk>
|
||||
Andy Pan <panjf2000@gmail.com> <i@andypan.me>
|
||||
Bert Belder <bertbelder@gmail.com> <i@bertbelder.com>
|
||||
Bert Belder <bertbelder@gmail.com> <info@2bs.nl>
|
||||
Bert Belder <bertbelder@gmail.com> <user@ChrUbuntu.(none)>
|
||||
@ -18,6 +19,7 @@ David Carlier <devnexen@gmail.com>
|
||||
Devchandra Meetei Leishangthem <dlmeetei@gmail.com>
|
||||
Fedor Indutny <fedor.indutny@gmail.com> <fedor@indutny.com>
|
||||
Frank Denis <github@pureftpd.org>
|
||||
Hüseyin Açacak <110401522+huseyinacacak-janea@users.noreply.github.com> <huseyin@janeasystems.com>
|
||||
Imran Iqbal <imrani@ca.ibm.com> <imran@imraniqbal.org>
|
||||
Isaac Z. Schlueter <i@izs.me>
|
||||
Jason Williams <necmon@yahoo.com>
|
||||
@ -29,6 +31,7 @@ Keno Fischer <kenof@stanford.edu> <kfischer+github@college.harvard.edu>
|
||||
Keno Fischer <kenof@stanford.edu> <kfischer@college.harvard.edu>
|
||||
Leith Bade <leith@leithalweapon.geek.nz> <leith@mapbox.com>
|
||||
Leonard Hecker <leonard.hecker91@gmail.com> <leonard@hecker.io>
|
||||
Lewis Russell <me@lewisr.dev> <lewis6991@gmail.com>
|
||||
Maciej Małecki <maciej.malecki@notimplemented.org> <me@mmalecki.com>
|
||||
Marc Schlaich <marc.schlaich@googlemail.com> <marc.schlaich@gmail.com>
|
||||
Michael <michael_dawson@ca.ibm.com>
|
||||
@ -36,6 +39,7 @@ Michael Neumann <mneumann@think.localnet> <mneumann@ntecs.de>
|
||||
Michael Penick <michael.penick@datastax.com> <mpenick@users.noreply.github.com>
|
||||
Nicholas Vavilov <vvnicholas@gmail.com>
|
||||
Nick Logan <ugexe@cpan.org> <nlogan@gmail.com>
|
||||
Olivier Valentin <ovalenti@redhat.com> <valentio@free.fr>
|
||||
Rasmus Christian Pedersen <zerhacken@yahoo.com>
|
||||
Rasmus Christian Pedersen <zerhacken@yahoo.com> <ruysch@outlook.com>
|
||||
Richard Lau <rlau@redhat.com> <riclau@uk.ibm.com>
|
||||
@ -46,7 +50,8 @@ Sakthipriyan Vairamani <thechargingvolcano@gmail.com>
|
||||
Sam Roberts <vieuxtech@gmail.com> <sam@strongloop.com>
|
||||
San-Tai Hsu <vanilla@fatpipi.com>
|
||||
Santiago Gimeno <santiago.gimeno@quantion.es> <santiago.gimeno@gmail.com>
|
||||
Saúl Ibarra Corretgé <saghul@gmail.com>
|
||||
Saúl Ibarra Corretgé <s@saghul.net>
|
||||
Saúl Ibarra Corretgé <s@saghul.net> <saghul@gmail.com>
|
||||
Saúl Ibarra Corretgé <saghul@gmail.com> <s@saghul.net>
|
||||
Shigeki Ohtsu <ohtsu@iij.ad.jp> <ohtsu@ohtsu.org>
|
||||
Shuowang (Wayne) Zhang <shuowang.zhang@ibm.com>
|
||||
@ -60,5 +65,7 @@ gengjiawen <technicalcute@gmail.com>
|
||||
jBarz <jBarz@users.noreply.github.com> <jbarboza@ca.ibm.com>
|
||||
jBarz <jBarz@users.noreply.github.com> <jbarz@users.noreply.github.com>
|
||||
ptlomholt <pt@lomholt.com>
|
||||
theanarkh <2923878201@qq.com> <theratliter@gmail.com>
|
||||
tjarlama <59913901+tjarlama@users.noreply.github.com> <tjarlama@gmail.com>
|
||||
ywave620 <rogertyang@tencent.com> <60539365+ywave620@users.noreply.github.com>
|
||||
zlargon <zlargon1988@gmail.com>
|
||||
|
||||
@ -2,10 +2,14 @@ version: 2
|
||||
|
||||
sphinx:
|
||||
builder: html
|
||||
configuration: null
|
||||
configuration: docs/src/conf.py
|
||||
fail_on_warning: false
|
||||
|
||||
build:
|
||||
os: "ubuntu-22.04"
|
||||
tools:
|
||||
python: "3.9"
|
||||
|
||||
python:
|
||||
version: 3.8
|
||||
install:
|
||||
- requirements: docs/requirements.txt
|
||||
|
||||
96
AUTHORS
96
AUTHORS
@ -496,3 +496,99 @@ Jesper Storm Bache <jsbache@users.noreply.github.com>
|
||||
Campbell He <duskmoon314@users.noreply.github.com>
|
||||
Andrey Hohutkin <andrey.hohutkin@gmail.com>
|
||||
deal <halx99@live.com>
|
||||
David Machaj <46852402+dmachaj@users.noreply.github.com>
|
||||
Jessica Clarke <jrtc27@jrtc27.com>
|
||||
Jeremy Rose <nornagon@nornagon.net>
|
||||
woclass <git@wo-class.cn>
|
||||
Luca Adrian L <info@lucalindhorst.de>
|
||||
WenTao Ou <owt5008137@live.com>
|
||||
jonilaitinen <joni.laitinen@iki.fi>
|
||||
UMU <UMU618@users.noreply.github.com>
|
||||
Paul Evans <leonerd@leonerd.org.uk>
|
||||
wyckster <wyckster@hotmail.com>
|
||||
Vittore F. Scolari <vittore.scolari@gmail.com>
|
||||
roflcopter4 <15476346+roflcopter4@users.noreply.github.com>
|
||||
V-for-Vasili <vasili.skurydzin@protonmail.com>
|
||||
Denny C. Dai <dennycd@me.com>
|
||||
Hannah Shi <hannahshisfb@gmail.com>
|
||||
tuftedocelot <tuftedocelot@fastmail.fm>
|
||||
blogdaren <blogdaren@163.com>
|
||||
chucksilvers <chuq@chuq.com>
|
||||
Sergey Fedorov <vital.had@gmail.com>
|
||||
theanarkh <2923878201@qq.com>
|
||||
Samuel Cabrero <samuelcabrero@gmail.com>
|
||||
自发对称破缺 <429839446@qq.com>
|
||||
Luan Devecchi <luan@engineer.com>
|
||||
Steven Schveighoffer <schveiguy@gmail.com>
|
||||
number201724 <number201724@me.com>
|
||||
Daniel <reymond315qq@gmail.com>
|
||||
Christian Clason <christian.clason@uni-due.de>
|
||||
ywave620 <rogertyang@tencent.com>
|
||||
jensbjorgensen <jbj1@ultraemail.net>
|
||||
daomingq <daoming.qiu@intel.com>
|
||||
Qix <Qix-@users.noreply.github.com>
|
||||
Edward Humes <29870961+aurxenon@users.noreply.github.com>
|
||||
Tim Besard <tim.besard@gmail.com>
|
||||
Sergey Rubanov <chi187@gmail.com>
|
||||
Stefan Stojanovic <StefanStojanovic@users.noreply.github.com>
|
||||
Zvicii <zvicii@qq.com>
|
||||
dundargoc <33953936+dundargoc@users.noreply.github.com>
|
||||
Jack·Boos·Yu <47264268+JackBoosY@users.noreply.github.com>
|
||||
panran <310762957@qq.com>
|
||||
Tamás Bálint Misius <lbphacker@gmail.com>
|
||||
Bruno Passeri <Varstahl@users.noreply.github.com>
|
||||
Jason Zhang <xzha4350@gmail.com>
|
||||
Lewis Russell <me@lewisr.dev>
|
||||
sivadeilra <arlie.davis@gmail.com>
|
||||
cui fliter <imcusg@gmail.com>
|
||||
Mohammed Keyvanzadeh <mohammadkeyvanzade94@gmail.com>
|
||||
Niklas Mischkulnig <4586894+mischnic@users.noreply.github.com>
|
||||
Stefan Karpinski <stefan@karpinski.org>
|
||||
liuxiang88 <94350585+liuxiang88@users.noreply.github.com>
|
||||
Jeffrey H. Johnson <trnsz@pobox.com>
|
||||
Abdirahim Musse <33973272+abmusse@users.noreply.github.com>
|
||||
小明 <7737673+caobug@users.noreply.github.com>
|
||||
Shuduo Sang <sangshuduo@gmail.com>
|
||||
Keith Winstein <keithw@cs.stanford.edu>
|
||||
michalbiesek <michalbiesek@gmail.com>
|
||||
Alois Klink <alois@aloisklink.com>
|
||||
SmorkalovG <smorkalov.g@gmail.com>
|
||||
Pleuvens <pleuvens.fervil@gmail.com>
|
||||
jolai <58589285+laijonathan@users.noreply.github.com>
|
||||
Julien Roncaglia <fox@vbfox.net>
|
||||
prubel <paul@rubels.net>
|
||||
Per Allansson <65364157+per-allansson@users.noreply.github.com>
|
||||
Matheus Izvekov <mizvekov@gmail.com>
|
||||
Christian Heimlich <chris@pcserenity.com>
|
||||
Hao Hu <33607772+hhu8@users.noreply.github.com>
|
||||
matoro <12038583+matoro@users.noreply.github.com>
|
||||
Bo Anderson <mail@boanderson.me>
|
||||
Ardi Nugraha <33378542+ardi-nugraha@users.noreply.github.com>
|
||||
Anton Bachin <antonbachin@yahoo.com>
|
||||
Trevor Flynn <trevorflynn@liquidcrystalstudios.com>
|
||||
Andy Pan <panjf2000@gmail.com>
|
||||
Viacheslav Muravyev <slavamuravey@mail.ru>
|
||||
Anthony Alayo <anthony.alayo@gmail.com>
|
||||
Thomas Walter <31201229+waltoss@users.noreply.github.com>
|
||||
hiiizxf <385122613@qq.com>
|
||||
Geddy <guandichao@163.com>
|
||||
Farzin Monsef <monseffarzin@gmail.com>
|
||||
tgolang <154592711+tgolang@users.noreply.github.com>
|
||||
josedelinux <josedelinux@hotmail.com>
|
||||
Hüseyin Açacak <110401522+huseyinacacak-janea@users.noreply.github.com>
|
||||
Uilian Ries <uilianries@gmail.com>
|
||||
Olivier Valentin <ovalenti@redhat.com>
|
||||
郑苏波 (Super Zheng) <superzheng@tencent.com>
|
||||
zeertzjq <zeertzjq@outlook.com>
|
||||
Ian Butterworth <i.r.butterworth@gmail.com>
|
||||
握猫猫 <164346864@qq.com>
|
||||
Zuohui Yang <274048862@qq.com>
|
||||
Edigleysson Silva (Edy) <edigleyssonsilva@gmail.com>
|
||||
Raihaan Shouhell <raihaanhimself@gmail.com>
|
||||
Rialbat <miha-wead@mail.ru>
|
||||
Adam <adam@NetBSD.org>
|
||||
Poul T Lomholt <ptlomholt@users.noreply.github.com>
|
||||
Thad House <ThadHouse@users.noreply.github.com>
|
||||
Julian A Avar C <28635807+julian-a-avar-c@users.noreply.github.com>
|
||||
amcgoogan <105525867+amcgoogan@users.noreply.github.com>
|
||||
Rafael Gonzaga <rafael.nunu@hotmail.com>
|
||||
|
||||
205
CMakeLists.txt
205
CMakeLists.txt
@ -1,8 +1,13 @@
|
||||
cmake_minimum_required(VERSION 3.4)
|
||||
project(libuv LANGUAGES C)
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
|
||||
cmake_policy(SET CMP0057 NEW) # Enable IN_LIST operator
|
||||
cmake_policy(SET CMP0064 NEW) # Support if (TEST) operator
|
||||
if(POLICY CMP0091)
|
||||
cmake_policy(SET CMP0091 NEW) # Enable MSVC_RUNTIME_LIBRARY setting
|
||||
endif()
|
||||
if(POLICY CMP0092)
|
||||
cmake_policy(SET CMP0092 NEW) # disable /W3 warning, if possible
|
||||
endif()
|
||||
|
||||
project(libuv LANGUAGES C)
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")
|
||||
|
||||
@ -17,9 +22,13 @@ set(CMAKE_C_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_C_EXTENSIONS ON)
|
||||
set(CMAKE_C_STANDARD 90)
|
||||
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
|
||||
option(LIBUV_BUILD_SHARED "Build shared lib" ON)
|
||||
|
||||
cmake_dependent_option(LIBUV_BUILD_TESTS
|
||||
"Build the unit tests when BUILD_TESTING is enabled and we are the root project" ON
|
||||
"BUILD_TESTING;CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR" OFF)
|
||||
"BUILD_TESTING;LIBUV_BUILD_SHARED;CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR" OFF)
|
||||
cmake_dependent_option(LIBUV_BUILD_BENCH
|
||||
"Build the benchmarks when building unit tests and we are the root project" ON
|
||||
"LIBUV_BUILD_TESTS" OFF)
|
||||
@ -27,28 +36,66 @@ cmake_dependent_option(LIBUV_BUILD_BENCH
|
||||
# Qemu Build
|
||||
option(QEMU "build for qemu" OFF)
|
||||
if(QEMU)
|
||||
add_definitions(-D__QEMU__=1)
|
||||
list(APPEND uv_defines __QEMU__=1)
|
||||
endif()
|
||||
|
||||
# Note: these are mutually exclusive.
|
||||
option(ASAN "Enable AddressSanitizer (ASan)" OFF)
|
||||
option(MSAN "Enable MemorySanitizer (MSan)" OFF)
|
||||
option(TSAN "Enable ThreadSanitizer (TSan)" OFF)
|
||||
option(UBSAN "Enable UndefinedBehaviorSanitizer (UBSan)" OFF)
|
||||
|
||||
if((ASAN OR TSAN) AND NOT (CMAKE_C_COMPILER_ID MATCHES "AppleClang|GNU|Clang"))
|
||||
message(SEND_ERROR "Sanitizer support requires clang or gcc. Try again with -DCMAKE_C_COMPILER.")
|
||||
if(MSAN AND NOT CMAKE_C_COMPILER_ID MATCHES "AppleClang|Clang")
|
||||
message(SEND_ERROR "MemorySanitizer requires clang. Try again with -DCMAKE_C_COMPILER=clang")
|
||||
endif()
|
||||
|
||||
if(ASAN)
|
||||
add_definitions(-D__ASAN__=1)
|
||||
list(APPEND uv_defines __ASAN__=1)
|
||||
if(CMAKE_C_COMPILER_ID MATCHES "AppleClang|GNU|Clang")
|
||||
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-omit-frame-pointer -fsanitize=address")
|
||||
set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fno-omit-frame-pointer -fsanitize=address")
|
||||
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fno-omit-frame-pointer -fsanitize=address")
|
||||
elseif(MSVC)
|
||||
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /fsanitize=address")
|
||||
else()
|
||||
message(SEND_ERROR "AddressSanitizer support requires clang, gcc, or msvc. Try again with -DCMAKE_C_COMPILER.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(MSAN)
|
||||
list(APPEND uv_defines __MSAN__=1)
|
||||
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-omit-frame-pointer -fsanitize=memory")
|
||||
set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fno-omit-frame-pointer -fsanitize=memory")
|
||||
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fno-omit-frame-pointer -fsanitize=memory")
|
||||
endif()
|
||||
|
||||
if(TSAN)
|
||||
add_definitions(-D__TSAN__=1)
|
||||
list(APPEND uv_defines __TSAN__=1)
|
||||
if(CMAKE_C_COMPILER_ID MATCHES "AppleClang|GNU|Clang")
|
||||
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-omit-frame-pointer -fsanitize=thread")
|
||||
set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fno-omit-frame-pointer -fsanitize=thread")
|
||||
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fno-omit-frame-pointer -fsanitize=thread")
|
||||
else()
|
||||
message(SEND_ERROR "ThreadSanitizer support requires clang or gcc. Try again with -DCMAKE_C_COMPILER.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(UBSAN)
|
||||
cmake_minimum_required(VERSION 3.13)
|
||||
list(APPEND uv_defines __UBSAN__=1)
|
||||
if(CMAKE_C_COMPILER_ID MATCHES "AppleClang|GNU|Clang")
|
||||
add_compile_options("-fsanitize=undefined" "-fno-sanitize-recover=undefined")
|
||||
if (NOT WIN32)
|
||||
add_link_options("-fsanitize=undefined")
|
||||
endif()
|
||||
if(MSVC)
|
||||
add_compile_options("/Oy-")
|
||||
else()
|
||||
add_compile_options("-fno-omit-frame-pointer")
|
||||
endif()
|
||||
else()
|
||||
message(SEND_ERROR "UndefinedBehaviorSanitizer support requires clang or gcc. Try again with -DCMAKE_C_COMPILER.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Compiler check
|
||||
@ -119,12 +166,19 @@ list(APPEND uv_cflags ${lint-utf8-msvc} )
|
||||
check_c_compiler_flag(-fno-strict-aliasing UV_F_STRICT_ALIASING)
|
||||
list(APPEND uv_cflags $<$<BOOL:${UV_F_STRICT_ALIASING}>:-fno-strict-aliasing>)
|
||||
|
||||
if (MSVC)
|
||||
# Error on calling undeclared functions.
|
||||
list(APPEND uv_cflags "/we4013")
|
||||
endif()
|
||||
|
||||
set(uv_sources
|
||||
src/fs-poll.c
|
||||
src/idna.c
|
||||
src/inet.c
|
||||
src/random.c
|
||||
src/strscpy.c
|
||||
src/strtok.c
|
||||
src/thread-common.c
|
||||
src/threadpool.c
|
||||
src/timer.c
|
||||
src/uv-common.c
|
||||
@ -132,14 +186,17 @@ set(uv_sources
|
||||
src/version.c)
|
||||
|
||||
if(WIN32)
|
||||
list(APPEND uv_defines WIN32_LEAN_AND_MEAN _WIN32_WINNT=0x0602)
|
||||
list(APPEND uv_defines WIN32_LEAN_AND_MEAN _WIN32_WINNT=0x0A00 _CRT_DECLARE_NONSTDC_NAMES=0)
|
||||
list(APPEND uv_libraries
|
||||
psapi
|
||||
user32
|
||||
advapi32
|
||||
iphlpapi
|
||||
userenv
|
||||
ws2_32)
|
||||
ws2_32
|
||||
dbghelp
|
||||
ole32
|
||||
shell32)
|
||||
list(APPEND uv_sources
|
||||
src/win/async.c
|
||||
src/win/core.c
|
||||
@ -215,16 +272,11 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Android")
|
||||
list(APPEND uv_defines _GNU_SOURCE)
|
||||
list(APPEND uv_libraries dl)
|
||||
list(APPEND uv_sources
|
||||
src/unix/android-ifaddrs.c
|
||||
src/unix/linux-core.c
|
||||
src/unix/linux-inotify.c
|
||||
src/unix/linux-syscalls.c
|
||||
src/unix/linux.c
|
||||
src/unix/procfs-exepath.c
|
||||
src/unix/pthread-fixes.c
|
||||
src/unix/random-getentropy.c
|
||||
src/unix/random-getrandom.c
|
||||
src/unix/random-sysctl-linux.c
|
||||
src/unix/epoll.c)
|
||||
src/unix/random-sysctl-linux.c)
|
||||
endif()
|
||||
|
||||
if(APPLE OR CMAKE_SYSTEM_NAME MATCHES "Android|Linux")
|
||||
@ -259,17 +311,26 @@ if(APPLE)
|
||||
src/unix/fsevents.c)
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "GNU")
|
||||
list(APPEND uv_defines _GNU_SOURCE _POSIX_C_SOURCE=200112 _XOPEN_SOURCE=500)
|
||||
list(APPEND uv_libraries dl)
|
||||
list(APPEND uv_sources
|
||||
src/unix/bsd-ifaddrs.c
|
||||
src/unix/no-fsevents.c
|
||||
src/unix/no-proctitle.c
|
||||
src/unix/posix-hrtime.c
|
||||
src/unix/posix-poll.c
|
||||
src/unix/hurd.c)
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||
list(APPEND uv_defines _GNU_SOURCE _POSIX_C_SOURCE=200112)
|
||||
list(APPEND uv_libraries dl rt)
|
||||
list(APPEND uv_sources
|
||||
src/unix/linux-core.c
|
||||
src/unix/linux-inotify.c
|
||||
src/unix/linux-syscalls.c
|
||||
src/unix/linux.c
|
||||
src/unix/procfs-exepath.c
|
||||
src/unix/random-getrandom.c
|
||||
src/unix/random-sysctl-linux.c
|
||||
src/unix/epoll.c)
|
||||
src/unix/random-sysctl-linux.c)
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "NetBSD")
|
||||
@ -300,7 +361,6 @@ if(CMAKE_SYSTEM_NAME STREQUAL "OS390")
|
||||
list(APPEND uv_defines _XOPEN_SOURCE=600)
|
||||
list(APPEND uv_defines _XOPEN_SOURCE_EXTENDED)
|
||||
list(APPEND uv_sources
|
||||
src/unix/pthread-fixes.c
|
||||
src/unix/os390.c
|
||||
src/unix/os390-syscalls.c
|
||||
src/unix/os390-proctitle.c)
|
||||
@ -338,6 +398,10 @@ if(CMAKE_SYSTEM_NAME STREQUAL "OS400")
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "SunOS")
|
||||
if(CMAKE_SYSTEM_VERSION STREQUAL "5.10")
|
||||
list(APPEND uv_defines SUNOS_NO_IFADDRS)
|
||||
list(APPEND uv_libraries rt)
|
||||
endif()
|
||||
list(APPEND uv_defines __EXTENSIONS__ _XOPEN_SOURCE=500 _REENTRANT)
|
||||
list(APPEND uv_libraries kstat nsl sendfile socket)
|
||||
list(APPEND uv_sources
|
||||
@ -372,6 +436,21 @@ if(APPLE OR CMAKE_SYSTEM_NAME MATCHES "DragonFly|FreeBSD|Linux|NetBSD|OpenBSD")
|
||||
list(APPEND uv_test_libraries util)
|
||||
endif()
|
||||
|
||||
if(CYGWIN OR MSYS)
|
||||
list(APPEND uv_defines _GNU_SOURCE)
|
||||
list(APPEND uv_sources
|
||||
src/unix/cygwin.c
|
||||
src/unix/bsd-ifaddrs.c
|
||||
src/unix/no-fsevents.c
|
||||
src/unix/no-proctitle.c
|
||||
src/unix/posix-hrtime.c
|
||||
src/unix/posix-poll.c
|
||||
src/unix/procfs-exepath.c
|
||||
src/unix/sysinfo-loadavg.c
|
||||
src/unix/sysinfo-memory.c)
|
||||
endif()
|
||||
|
||||
if(LIBUV_BUILD_SHARED)
|
||||
add_library(uv SHARED ${uv_sources})
|
||||
target_compile_definitions(uv
|
||||
INTERFACE
|
||||
@ -391,6 +470,8 @@ if(CMAKE_SYSTEM_NAME STREQUAL "OS390")
|
||||
set_target_properties(uv PROPERTIES LINKER_LANGUAGE CXX)
|
||||
endif()
|
||||
target_link_libraries(uv ${uv_libraries})
|
||||
set_target_properties(uv PROPERTIES OUTPUT_NAME "uv")
|
||||
endif()
|
||||
|
||||
add_library(uv_a STATIC ${uv_sources})
|
||||
target_compile_definitions(uv_a PRIVATE ${uv_defines})
|
||||
@ -406,6 +487,10 @@ if(CMAKE_SYSTEM_NAME STREQUAL "OS390")
|
||||
set_target_properties(uv_a PROPERTIES LINKER_LANGUAGE CXX)
|
||||
endif()
|
||||
target_link_libraries(uv_a ${uv_libraries})
|
||||
set_target_properties(uv_a PROPERTIES OUTPUT_NAME "uv")
|
||||
if(WIN32)
|
||||
set_target_properties(uv_a PROPERTIES PREFIX "lib")
|
||||
endif()
|
||||
|
||||
if(LIBUV_BUILD_TESTS)
|
||||
# Small hack: use ${uv_test_sources} now to get the runner skeleton,
|
||||
@ -418,6 +503,7 @@ if(LIBUV_BUILD_TESTS)
|
||||
test/benchmark-fs-stat.c
|
||||
test/benchmark-getaddrinfo.c
|
||||
test/benchmark-loop-count.c
|
||||
test/benchmark-queue-work.c
|
||||
test/benchmark-million-async.c
|
||||
test/benchmark-million-timers.c
|
||||
test/benchmark-multi-accept.c
|
||||
@ -447,7 +533,6 @@ if(LIBUV_BUILD_TESTS)
|
||||
test/test-async-null-cb.c
|
||||
test/test-async.c
|
||||
test/test-barrier.c
|
||||
test/test-callback-order.c
|
||||
test/test-callback-stack.c
|
||||
test/test-close-fd.c
|
||||
test/test-close-order.c
|
||||
@ -487,6 +572,7 @@ if(LIBUV_BUILD_TESTS)
|
||||
test/test-hrtime.c
|
||||
test/test-idle.c
|
||||
test/test-idna.c
|
||||
test/test-iouring-pollhup.c
|
||||
test/test-ip4-addr.c
|
||||
test/test-ip6-addr.c
|
||||
test/test-ip-name.c
|
||||
@ -546,10 +632,12 @@ if(LIBUV_BUILD_TESTS)
|
||||
test/test-spawn.c
|
||||
test/test-stdio-over-pipes.c
|
||||
test/test-strscpy.c
|
||||
test/test-strtok.c
|
||||
test/test-tcp-alloc-cb-fail.c
|
||||
test/test-tcp-bind-error.c
|
||||
test/test-tcp-bind6-error.c
|
||||
test/test-tcp-close-accept.c
|
||||
test/test-tcp-close-after-read-timeout.c
|
||||
test/test-tcp-close-while-connecting.c
|
||||
test/test-tcp-close.c
|
||||
test/test-tcp-close-reset.c
|
||||
@ -562,9 +650,12 @@ if(LIBUV_BUILD_TESTS)
|
||||
test/test-tcp-oob.c
|
||||
test/test-tcp-open.c
|
||||
test/test-tcp-read-stop.c
|
||||
test/test-tcp-reuseport.c
|
||||
test/test-tcp-read-stop-start.c
|
||||
test/test-tcp-rst.c
|
||||
test/test-tcp-shutdown-after-write.c
|
||||
test/test-tcp-try-write.c
|
||||
test/test-tcp-write-in-a-row.c
|
||||
test/test-tcp-try-write-error.c
|
||||
test/test-tcp-unexpected-read.c
|
||||
test/test-tcp-write-after-connect.c
|
||||
@ -573,8 +664,11 @@ if(LIBUV_BUILD_TESTS)
|
||||
test/test-tcp-write-to-half-open-connection.c
|
||||
test/test-tcp-writealot.c
|
||||
test/test-test-macros.c
|
||||
test/test-thread-affinity.c
|
||||
test/test-thread-equal.c
|
||||
test/test-thread.c
|
||||
test/test-thread-name.c
|
||||
test/test-thread-priority.c
|
||||
test/test-threadpool-cancel.c
|
||||
test/test-threadpool.c
|
||||
test/test-timer-again.c
|
||||
@ -605,6 +699,8 @@ if(LIBUV_BUILD_TESTS)
|
||||
test/test-udp-sendmmsg-error.c
|
||||
test/test-udp-send-unreachable.c
|
||||
test/test-udp-try-send.c
|
||||
test/test-udp-recv-in-a-row.c
|
||||
test/test-udp-reuseport.c
|
||||
test/test-uname.c
|
||||
test/test-walk-handles.c
|
||||
test/test-watcher-cross-stop.c)
|
||||
@ -621,6 +717,12 @@ if(LIBUV_BUILD_TESTS)
|
||||
set_tests_properties(uv_test PROPERTIES ENVIRONMENT
|
||||
"LIBPATH=${CMAKE_BINARY_DIR}:$ENV{LIBPATH}")
|
||||
endif()
|
||||
if(WIN32)
|
||||
add_custom_command(TARGET uv_run_tests POST_BUILD
|
||||
COMMAND "${CMAKE_COMMAND}" -E copy
|
||||
"$<TARGET_FILE:uv_run_tests>"
|
||||
"$<TARGET_FILE_DIR:uv_run_tests>/uv_run_tests_no_ext")
|
||||
endif()
|
||||
add_executable(uv_run_tests_a ${uv_test_sources} uv_win_longpath.manifest)
|
||||
target_compile_definitions(uv_run_tests_a PRIVATE ${uv_defines})
|
||||
target_compile_options(uv_run_tests_a PRIVATE ${uv_cflags})
|
||||
@ -637,6 +739,12 @@ if(LIBUV_BUILD_TESTS)
|
||||
set_target_properties(uv_run_tests PROPERTIES LINKER_LANGUAGE CXX)
|
||||
set_target_properties(uv_run_tests_a PROPERTIES LINKER_LANGUAGE CXX)
|
||||
endif()
|
||||
if(WIN32)
|
||||
add_custom_command(TARGET uv_run_tests_a POST_BUILD
|
||||
COMMAND "${CMAKE_COMMAND}" -E copy
|
||||
"$<TARGET_FILE:uv_run_tests_a>"
|
||||
"$<TARGET_FILE_DIR:uv_run_tests_a>/uv_run_tests_a_no_ext")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Now for some gibbering horrors from beyond the stars...
|
||||
@ -648,29 +756,54 @@ string(REPLACE ";" " " LIBS "${LIBS}")
|
||||
file(STRINGS configure.ac configure_ac REGEX ^AC_INIT)
|
||||
string(REGEX MATCH "([0-9]+)[.][0-9]+[.][0-9]+" PACKAGE_VERSION "${configure_ac}")
|
||||
set(UV_VERSION_MAJOR "${CMAKE_MATCH_1}")
|
||||
# The version in the filename is mirroring the behaviour of autotools.
|
||||
set_target_properties(uv PROPERTIES
|
||||
VERSION ${UV_VERSION_MAJOR}.0.0
|
||||
SOVERSION ${UV_VERSION_MAJOR})
|
||||
|
||||
set(includedir ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR})
|
||||
set(libdir ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR})
|
||||
set(prefix ${CMAKE_INSTALL_PREFIX})
|
||||
configure_file(libuv.pc.in libuv.pc @ONLY)
|
||||
configure_file(libuv-static.pc.in libuv-static.pc @ONLY)
|
||||
|
||||
install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
|
||||
install(FILES LICENSE DESTINATION ${CMAKE_INSTALL_DOCDIR})
|
||||
install(FILES ${PROJECT_BINARY_DIR}/libuv.pc ${PROJECT_BINARY_DIR}/libuv-static.pc
|
||||
install(FILES LICENSE-extra DESTINATION ${CMAKE_INSTALL_DOCDIR})
|
||||
install(FILES ${PROJECT_BINARY_DIR}/libuv-static.pc
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
|
||||
install(TARGETS uv_a EXPORT libuvConfig
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
install(EXPORT libuvConfig
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/libuv
|
||||
NAMESPACE libuv::)
|
||||
|
||||
if(LIBUV_BUILD_SHARED)
|
||||
# The version in the filename is mirroring the behaviour of autotools.
|
||||
set_target_properties(uv PROPERTIES
|
||||
VERSION ${UV_VERSION_MAJOR}.0.0
|
||||
SOVERSION ${UV_VERSION_MAJOR})
|
||||
configure_file(libuv.pc.in libuv.pc @ONLY)
|
||||
install(FILES ${PROJECT_BINARY_DIR}/libuv.pc
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
|
||||
install(TARGETS uv EXPORT libuvConfig
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
install(TARGETS uv_a ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
install(EXPORT libuvConfig DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/libuv)
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
set(CMAKE_DEBUG_POSTFIX d)
|
||||
get_filename_component(CMAKE_C_COMPILER_DIR ${CMAKE_C_COMPILER} DIRECTORY)
|
||||
if(ASAN)
|
||||
file(INSTALL "${CMAKE_C_COMPILER_DIR}/llvm-symbolizer.exe" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
file(INSTALL "${CMAKE_C_COMPILER_DIR}/clang_rt.asan_dynamic-x86_64.dll" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
file(INSTALL "${CMAKE_C_COMPILER_DIR}/clang_rt.asan_dbg_dynamic-x86_64.dll" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(BUILD_SHARED_LIBS)
|
||||
set(LIB_SELECTED uv)
|
||||
else()
|
||||
set(LIB_SELECTED uv_a)
|
||||
endif()
|
||||
|
||||
add_library(libuv::libuv ALIAS ${LIB_SELECTED})
|
||||
|
||||
message(STATUS "summary of build options:
|
||||
Install prefix: ${CMAKE_INSTALL_PREFIX}
|
||||
|
||||
51
LICENSE
51
LICENSE
@ -1,6 +1,3 @@
|
||||
libuv is licensed for use as follows:
|
||||
|
||||
====
|
||||
Copyright (c) 2015-present libuv project contributors.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
@ -20,51 +17,3 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
IN THE SOFTWARE.
|
||||
====
|
||||
|
||||
This license applies to parts of libuv originating from the
|
||||
https://github.com/joyent/libuv repository:
|
||||
|
||||
====
|
||||
|
||||
Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to
|
||||
deal in the Software without restriction, including without limitation the
|
||||
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
sell copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
IN THE SOFTWARE.
|
||||
|
||||
====
|
||||
|
||||
This license applies to all parts of libuv that are not externally
|
||||
maintained libraries.
|
||||
|
||||
The externally maintained libraries used by libuv are:
|
||||
|
||||
- tree.h (from FreeBSD), copyright Niels Provos. Two clause BSD license.
|
||||
|
||||
- inet_pton and inet_ntop implementations, contained in src/inet.c, are
|
||||
copyright the Internet Systems Consortium, Inc., and licensed under the ISC
|
||||
license.
|
||||
|
||||
- stdint-msvc2008.h (from msinttypes), copyright Alexander Chemeris. Three
|
||||
clause BSD license.
|
||||
|
||||
- pthread-fixes.c, copyright Google Inc. and Sony Mobile Communications AB.
|
||||
Three clause BSD license.
|
||||
|
||||
- android-ifaddrs.h, android-ifaddrs.c, copyright Berkeley Software Design
|
||||
Inc, Kenneth MacKay and Emergya (Cloud4all, FP7/2007-2013, grant agreement
|
||||
n° 289016). Three clause BSD license.
|
||||
|
||||
36
LICENSE-extra
Normal file
36
LICENSE-extra
Normal file
@ -0,0 +1,36 @@
|
||||
This license applies to parts of libuv originating from the
|
||||
https://github.com/joyent/libuv repository:
|
||||
|
||||
====
|
||||
|
||||
Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to
|
||||
deal in the Software without restriction, including without limitation the
|
||||
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
sell copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
IN THE SOFTWARE.
|
||||
|
||||
====
|
||||
|
||||
This license applies to all parts of libuv that are not externally
|
||||
maintained libraries.
|
||||
|
||||
The externally maintained libraries used by libuv are:
|
||||
|
||||
- tree.h (from FreeBSD), copyright Niels Provos. Two clause BSD license.
|
||||
|
||||
- inet_pton and inet_ntop implementations, contained in src/inet.c, are
|
||||
copyright the Internet Systems Consortium, Inc., and licensed under the ISC
|
||||
license.
|
||||
13
LINKS.md
13
LINKS.md
@ -1,16 +1,20 @@
|
||||
### Apps / VM
|
||||
* [AliceO2](https://github.com/AliceO2Group/AliceO2): The framework and detector specific code for the reconstruction, calibration and simulation for the ALICE experiment at CERN.
|
||||
* [Beam](https://github.com/BeamMW/beam): A scalable, confidential cryptocurrency based on the Mimblewimble protocol.
|
||||
* [BIND 9](https://bind.isc.org/): DNS software system including an authoritative server, a recursive resolver and related utilities.
|
||||
* [cjdns](https://github.com/cjdelisle/cjdns): Encrypted self-configuring network/VPN routing engine
|
||||
* [clearskies_core](https://github.com/larroy/clearskies_core): Clearskies file synchronization program. (C++11)
|
||||
* [CMake](https://cmake.org) open-source, cross-platform family of tools designed to build, test and package software
|
||||
* [Cocos-Engine](https://github.com/cocos/cocos-engine): The runtime framework for Cocos Creator editor.
|
||||
* [Coherence](https://github.com/liesware/coherence/): Cryptographic server for modern web apps.
|
||||
* [DPS8M](https://dps8m.gitlab.io): GE ∕ Honeywell ∕ Bull DPS‑8/M and 6180/L68 mainframe simulator.
|
||||
* [DPS-For-IoT](https://github.com/intel/dps-for-iot/wiki): Fully distributed publish/subscribe protocol.
|
||||
* [HashLink](https://github.com/HaxeFoundation/hashlink): Haxe run-time with libuv support included.
|
||||
* [Haywire](https://github.com/kellabyte/Haywire): Asynchronous HTTP server.
|
||||
* [H2O](https://github.com/h2o/h2o): An optimized HTTP server with support for HTTP/1.x and HTTP/2.
|
||||
* [Igropyr](https://github.com/guenchi/Igropyr): a async Scheme http server base on libuv.
|
||||
* [Julia](http://julialang.org/): Scientific computing programming language
|
||||
* [Kestrel](https://github.com/aspnet/AspNetCore/tree/master/src/Servers/Kestrel): web server (C# + libuv + [ASP.NET Core](http://github.com/aspnet))
|
||||
* [Kestrel](https://github.com/dotnet/aspnetcore/tree/main/src/Servers/Kestrel): web server (C# + libuv + [ASP.NET Core](http://github.com/aspnet))
|
||||
* [Knot DNS Resolver](https://www.knot-resolver.cz/): A minimalistic DNS caching resolver
|
||||
* [Lever](http://leverlanguage.com): runtime, libuv at the 0.9.0 release
|
||||
* [libnode](https://github.com/plenluno/libnode): C++ implementation of Node.js
|
||||
@ -30,8 +34,11 @@
|
||||
* [phastlight](https://github.com/phastlight/phastlight): Command line tool and web server written in PHP 5.3+ inspired by Node.js
|
||||
* [pilight](https://www.pilight.org/): home automation ("domotica")
|
||||
* [pixie](https://github.com/pixie-lang/pixie): clojure-inspired lisp with a tracing JIT
|
||||
* [Pixie-io](https://github.com/pixie-io/pixie): Open-source observability tool for Kubernetes applications.
|
||||
* [potion](https://github.com/perl11/potion)/[p2](https://github.com/perl11/p2): runtime
|
||||
* [racer](https://libraries.io/rubygems/racer): Ruby web server written as an C extension
|
||||
* [scala-native-loop](https://github.com/scala-native/scala-native-loop): Extensible event loop and async-oriented IO for Scala Native; powered by libuv
|
||||
* [Socket Runtime](https://sockets.sh): A runtime for creating native cross-platform software on mobile and desktop using HTML, CSS, and JavaScript
|
||||
* [spider-gazelle](https://github.com/cotag/spider-gazelle): Ruby web server using libuv bindings
|
||||
* [Suave](http://suave.io/): A simple web development F# library providing a lightweight web server and a set of combinators to manipulate route flow and task composition
|
||||
* [Swish](https://github.com/becls/swish/): Concurrency engine with Erlang-like concepts. Includes a web server.
|
||||
@ -39,6 +46,7 @@
|
||||
* [Urbit](http://urbit.org): runtime
|
||||
* [uv_callback](https://github.com/litesync/uv_callback) libuv thread communication
|
||||
* [uvloop](https://github.com/MagicStack/uvloop): Ultra fast implementation of python's asyncio event loop on top of libuv
|
||||
* [WPILib](https://github.com/wpilibsuite/allwpilib): Libraries for creating robot programs for the roboRIO.
|
||||
* [Wren CLI](https://github.com/wren-lang/wren-cli): For io, process, scheduler and timer modules
|
||||
|
||||
### Other
|
||||
@ -59,6 +67,7 @@
|
||||
* [lluv](https://github.com/moteus/lua-lluv)
|
||||
* C++11
|
||||
* [uvpp](https://github.com/larroy/uvpp) - Not complete, exposes very few aspects of `libuv`
|
||||
* [nsuv](https://github.com/nodesource/nsuv) - Template wrapper focused on enforcing compile-time type safety when propagating data
|
||||
* C++17
|
||||
* [uvw](https://github.com/skypjack/uvw) - Header-only, event based, tiny and easy to use *libuv* wrapper in modern C++.
|
||||
* Python
|
||||
@ -99,3 +108,5 @@
|
||||
* [node.pas](https://github.com/vovach777/node.pas) NodeJS-like ecosystem
|
||||
* Haskell
|
||||
* [Z.Haskell](https://z.haskell.world)
|
||||
* C3
|
||||
* [libuv.c3l](https://github.com/velikoss/libuv.c3l)
|
||||
|
||||
@ -1,23 +1,16 @@
|
||||
|
||||
# Project Maintainers
|
||||
|
||||
libuv is currently managed by the following individuals:
|
||||
|
||||
* **Anna Henningsen** ([@addaleax](https://github.com/addaleax))
|
||||
* **Bartosz Sosnowski** ([@bzoz](https://github.com/bzoz))
|
||||
* **Ben Noordhuis** ([@bnoordhuis](https://github.com/bnoordhuis))
|
||||
- GPG key: D77B 1E34 243F BAF0 5F8E 9CC3 4F55 C8C8 46AB 89B9 (pubkey-bnoordhuis)
|
||||
* **Bert Belder** ([@piscisaureus](https://github.com/piscisaureus))
|
||||
* **Colin Ihrig** ([@cjihrig](https://github.com/cjihrig))
|
||||
- GPG key: 94AE 3667 5C46 4D64 BAFA 68DD 7434 390B DBE9 B9C5 (pubkey-cjihrig)
|
||||
- GPG key: 5735 3E0D BDAA A7E8 39B6 6A1A FF47 D5E4 AD8B 4FDC (pubkey-cjihrig-kb)
|
||||
* **Fedor Indutny** ([@indutny](https://github.com/indutny))
|
||||
- GPG key: AF2E EA41 EC34 47BF DD86 FED9 D706 3CCE 19B7 E890 (pubkey-indutny)
|
||||
* **Imran Iqbal** ([@imran-iq](https://github.com/imran-iq))
|
||||
- GPG key: 9DFE AA5F 481B BF77 2D90 03CE D592 4925 2F8E C41A (pubkey-iwuzhere)
|
||||
* **Jameson Nash** ([@vtjnash](https://github.com/vtjnash))
|
||||
- GPG key: AEAD 0A4B 6867 6775 1A0E 4AEF 34A2 5FB1 2824 6514 (pubkey-vtjnash)
|
||||
* **John Barboza** ([@jbarz](https://github.com/jbarz))
|
||||
- GPG key: CFBB 9CA9 A5BE AFD7 0E2B 3C5A 79A6 7C55 A367 9C8B (pubkey2022-vtjnash)
|
||||
* **Jiawen Geng** ([@gengjiawen](https://github.com/gengjiawen))
|
||||
* **Kaoru Takanashi** ([@erw7](https://github.com/erw7))
|
||||
- GPG Key: 5804 F999 8A92 2AFB A398 47A0 7183 5090 6134 887F (pubkey-erw7)
|
||||
* **Richard Lau** ([@richardlau](https://github.com/richardlau))
|
||||
@ -26,6 +19,18 @@ libuv is currently managed by the following individuals:
|
||||
- GPG key: 612F 0EAD 9401 6223 79DF 4402 F28C 3C8D A33C 03BE (pubkey-santigimeno)
|
||||
* **Saúl Ibarra Corretgé** ([@saghul](https://github.com/saghul))
|
||||
- GPG key: FDF5 1936 4458 319F A823 3DC9 410E 5553 AE9B C059 (pubkey-saghul)
|
||||
* **Trevor Norris** ([@trevnorris](https://github.com/trevnorris))
|
||||
- GPG key: AEFC 279A 0C93 0676 7E58 29A1 251C A676 820D C7F3 (pubkey-trevnorris)
|
||||
|
||||
## Project Maintainers emeriti
|
||||
|
||||
* **Anna Henningsen** ([@addaleax](https://github.com/addaleax))
|
||||
* **Bartosz Sosnowski** ([@bzoz](https://github.com/bzoz))
|
||||
* **Bert Belder** ([@piscisaureus](https://github.com/piscisaureus))
|
||||
* **Fedor Indutny** ([@indutny](https://github.com/indutny))
|
||||
- GPG key: AF2E EA41 EC34 47BF DD86 FED9 D706 3CCE 19B7 E890 (pubkey-indutny)
|
||||
* **Imran Iqbal** ([@imran-iq](https://github.com/imran-iq))
|
||||
* **John Barboza** ([@jbarz](https://github.com/jbarz))
|
||||
|
||||
## Storing a maintainer key in Git
|
||||
|
||||
|
||||
59
Makefile.am
59
Makefile.am
@ -27,8 +27,8 @@ uvinclude_HEADERS = include/uv/errno.h \
|
||||
CLEANFILES =
|
||||
|
||||
lib_LTLIBRARIES = libuv.la
|
||||
libuv_la_CFLAGS = @CFLAGS@
|
||||
libuv_la_LDFLAGS = -no-undefined -version-info 1:0:0
|
||||
libuv_la_CFLAGS = $(AM_CFLAGS)
|
||||
libuv_la_LDFLAGS = $(AM_LDFLAGS) -no-undefined -version-info 1:0:0
|
||||
libuv_la_SOURCES = src/fs-poll.c \
|
||||
src/heap-inl.h \
|
||||
src/idna.c \
|
||||
@ -38,12 +38,15 @@ libuv_la_SOURCES = src/fs-poll.c \
|
||||
src/random.c \
|
||||
src/strscpy.c \
|
||||
src/strscpy.h \
|
||||
src/thread-common.c \
|
||||
src/threadpool.c \
|
||||
src/timer.c \
|
||||
src/uv-data-getter-setters.c \
|
||||
src/uv-common.c \
|
||||
src/uv-common.h \
|
||||
src/version.c
|
||||
src/version.c \
|
||||
src/strtok.c \
|
||||
src/strtok.h
|
||||
|
||||
if SUNOS
|
||||
# Can't be turned into a CC_CHECK_CFLAGS in configure.ac, it makes compilers
|
||||
@ -56,7 +59,7 @@ if WINNT
|
||||
uvinclude_HEADERS += include/uv/win.h include/uv/tree.h
|
||||
AM_CPPFLAGS += -I$(top_srcdir)/src/win \
|
||||
-DWIN32_LEAN_AND_MEAN \
|
||||
-D_WIN32_WINNT=0x0602
|
||||
-D_WIN32_WINNT=0x0A00
|
||||
libuv_la_SOURCES += src/win/async.c \
|
||||
src/win/atomicops-inl.h \
|
||||
src/win/core.c \
|
||||
@ -94,7 +97,6 @@ else # WINNT
|
||||
uvinclude_HEADERS += include/uv/unix.h
|
||||
AM_CPPFLAGS += -I$(top_srcdir)/src/unix
|
||||
libuv_la_SOURCES += src/unix/async.c \
|
||||
src/unix/atomic-ops.h \
|
||||
src/unix/core.c \
|
||||
src/unix/dl.c \
|
||||
src/unix/fs.c \
|
||||
@ -108,7 +110,6 @@ libuv_la_SOURCES += src/unix/async.c \
|
||||
src/unix/process.c \
|
||||
src/unix/random-devurandom.c \
|
||||
src/unix/signal.c \
|
||||
src/unix/spinlock.h \
|
||||
src/unix/stream.c \
|
||||
src/unix/tcp.c \
|
||||
src/unix/thread.c \
|
||||
@ -120,18 +121,26 @@ endif # WINNT
|
||||
EXTRA_DIST = test/fixtures/empty_file \
|
||||
test/fixtures/load_error.node \
|
||||
test/fixtures/lorem_ipsum.txt \
|
||||
test/fixtures/one_file/one_file \
|
||||
include \
|
||||
docs \
|
||||
img \
|
||||
CONTRIBUTING.md \
|
||||
LICENSE \
|
||||
LICENSE-extra \
|
||||
README.md
|
||||
|
||||
|
||||
|
||||
TESTS = test/run-tests
|
||||
check_PROGRAMS = test/run-tests
|
||||
test_run_tests_CFLAGS =
|
||||
test_run_tests_CFLAGS = $(AM_CFLAGS)
|
||||
|
||||
if WINNT
|
||||
check-am: test/run-tests_no_ext
|
||||
test/run-tests_no_ext: test/run-tests$(EXEEXT)
|
||||
cp test/run-tests$(EXEEXT) test/run-tests_no_ext
|
||||
endif
|
||||
|
||||
if SUNOS
|
||||
# Can't be turned into a CC_CHECK_CFLAGS in configure.ac, it makes compilers
|
||||
@ -139,7 +148,7 @@ if SUNOS
|
||||
test_run_tests_CFLAGS += -pthreads
|
||||
endif
|
||||
|
||||
test_run_tests_LDFLAGS =
|
||||
test_run_tests_LDFLAGS = $(AM_LDFLAGS)
|
||||
test_run_tests_SOURCES = test/blackhole-server.c \
|
||||
test/echo-server.c \
|
||||
test/run-tests.c \
|
||||
@ -150,7 +159,6 @@ test_run_tests_SOURCES = test/blackhole-server.c \
|
||||
test/test-async.c \
|
||||
test/test-async-null-cb.c \
|
||||
test/test-barrier.c \
|
||||
test/test-callback-order.c \
|
||||
test/test-callback-stack.c \
|
||||
test/test-close-fd.c \
|
||||
test/test-close-order.c \
|
||||
@ -190,6 +198,7 @@ test_run_tests_SOURCES = test/blackhole-server.c \
|
||||
test/test-hrtime.c \
|
||||
test/test-idle.c \
|
||||
test/test-idna.c \
|
||||
test/test-iouring-pollhup.c \
|
||||
test/test-ip4-addr.c \
|
||||
test/test-ip6-addr.c \
|
||||
test/test-ip-name.c \
|
||||
@ -250,11 +259,13 @@ test_run_tests_SOURCES = test/blackhole-server.c \
|
||||
test/test-spawn.c \
|
||||
test/test-stdio-over-pipes.c \
|
||||
test/test-strscpy.c \
|
||||
test/test-strtok.c \
|
||||
test/test-tcp-alloc-cb-fail.c \
|
||||
test/test-tcp-bind-error.c \
|
||||
test/test-tcp-bind6-error.c \
|
||||
test/test-tcp-close-accept.c \
|
||||
test/test-tcp-close-while-connecting.c \
|
||||
test/test-tcp-close-after-read-timeout.c \
|
||||
test/test-tcp-close.c \
|
||||
test/test-tcp-close-reset.c \
|
||||
test/test-tcp-create-socket-early.c \
|
||||
@ -265,7 +276,9 @@ test_run_tests_SOURCES = test/blackhole-server.c \
|
||||
test/test-tcp-flags.c \
|
||||
test/test-tcp-open.c \
|
||||
test/test-tcp-read-stop.c \
|
||||
test/test-tcp-reuseport.c \
|
||||
test/test-tcp-read-stop-start.c \
|
||||
test/test-tcp-rst.c \
|
||||
test/test-tcp-shutdown-after-write.c \
|
||||
test/test-tcp-unexpected-read.c \
|
||||
test/test-tcp-oob.c \
|
||||
@ -274,11 +287,15 @@ test_run_tests_SOURCES = test/blackhole-server.c \
|
||||
test/test-tcp-writealot.c \
|
||||
test/test-tcp-write-fail.c \
|
||||
test/test-tcp-try-write.c \
|
||||
test/test-tcp-write-in-a-row.c \
|
||||
test/test-tcp-try-write-error.c \
|
||||
test/test-tcp-write-queue-order.c \
|
||||
test/test-test-macros.c \
|
||||
test/test-thread-equal.c \
|
||||
test/test-thread.c \
|
||||
test/test-thread-affinity.c \
|
||||
test/test-thread-name.c \
|
||||
test/test-thread-priority.c \
|
||||
test/test-threadpool-cancel.c \
|
||||
test/test-threadpool.c \
|
||||
test/test-timer-again.c \
|
||||
@ -309,6 +326,8 @@ test_run_tests_SOURCES = test/blackhole-server.c \
|
||||
test/test-udp-sendmmsg-error.c \
|
||||
test/test-udp-send-unreachable.c \
|
||||
test/test-udp-try-send.c \
|
||||
test/test-udp-recv-in-a-row.c \
|
||||
test/test-udp-reuseport.c \
|
||||
test/test-uname.c \
|
||||
test/test-walk-handles.c \
|
||||
test/test-watcher-cross-stop.c
|
||||
@ -388,10 +407,7 @@ libuv_la_SOURCES += src/unix/aix-common.c \
|
||||
endif
|
||||
|
||||
if ANDROID
|
||||
uvinclude_HEADERS += include/uv/android-ifaddrs.h
|
||||
libuv_la_CFLAGS += -D_GNU_SOURCE
|
||||
libuv_la_SOURCES += src/unix/android-ifaddrs.c \
|
||||
src/unix/pthread-fixes.c
|
||||
endif
|
||||
|
||||
if CYGWIN
|
||||
@ -415,6 +431,7 @@ libuv_la_CFLAGS += -D_DARWIN_UNLIMITED_SELECT=1
|
||||
libuv_la_SOURCES += src/unix/bsd-ifaddrs.c \
|
||||
src/unix/darwin-proctitle.c \
|
||||
src/unix/darwin-stub.h \
|
||||
src/unix/darwin-syscalls.h \
|
||||
src/unix/darwin.c \
|
||||
src/unix/fsevents.c \
|
||||
src/unix/kqueue.c \
|
||||
@ -457,23 +474,22 @@ endif
|
||||
|
||||
if HURD
|
||||
uvinclude_HEADERS += include/uv/posix.h
|
||||
libuv_la_SOURCES += src/unix/no-fsevents.c \
|
||||
libuv_la_SOURCES += src/unix/bsd-ifaddrs.c \
|
||||
src/unix/no-fsevents.c \
|
||||
src/unix/no-proctitle.c \
|
||||
src/unix/posix-hrtime.c \
|
||||
src/unix/posix-poll.c
|
||||
src/unix/posix-poll.c \
|
||||
src/unix/hurd.c
|
||||
endif
|
||||
|
||||
if LINUX
|
||||
uvinclude_HEADERS += include/uv/linux.h
|
||||
libuv_la_CFLAGS += -D_GNU_SOURCE
|
||||
libuv_la_SOURCES += src/unix/linux-core.c \
|
||||
src/unix/linux-inotify.c \
|
||||
src/unix/linux-syscalls.c \
|
||||
src/unix/linux-syscalls.h \
|
||||
libuv_la_SOURCES += src/unix/linux.c \
|
||||
src/unix/procfs-exepath.c \
|
||||
src/unix/proctitle.c \
|
||||
src/unix/random-getrandom.c \
|
||||
src/unix/random-sysctl-linux.c \
|
||||
src/unix/epoll.c
|
||||
src/unix/random-sysctl-linux.c
|
||||
test_run_tests_LDFLAGS += -lutil
|
||||
endif
|
||||
|
||||
@ -537,8 +553,7 @@ libuv_la_CFLAGS += -D_UNIX03_THREADS \
|
||||
-qXPLINK \
|
||||
-qFLOAT=IEEE
|
||||
libuv_la_LDFLAGS += -qXPLINK
|
||||
libuv_la_SOURCES += src/unix/pthread-fixes.c \
|
||||
src/unix/os390.c \
|
||||
libuv_la_SOURCES += src/unix/os390.c \
|
||||
src/unix/os390-syscalls.c \
|
||||
src/unix/proctitle.c
|
||||
endif
|
||||
|
||||
28
README.md
28
README.md
@ -43,8 +43,11 @@ The ABI/API changes can be tracked [here](http://abi-laboratory.pro/tracker/time
|
||||
|
||||
## Licensing
|
||||
|
||||
libuv is licensed under the MIT license. Check the [LICENSE file](LICENSE).
|
||||
The documentation is licensed under the CC BY 4.0 license. Check the [LICENSE-docs file](LICENSE-docs).
|
||||
libuv is licensed under the MIT license. Check the [LICENSE](LICENSE) and
|
||||
[LICENSE-extra](LICENSE-extra) files.
|
||||
|
||||
The documentation is licensed under the CC BY 4.0 license. Check the
|
||||
[LICENSE-docs file](LICENSE-docs).
|
||||
|
||||
## Community
|
||||
|
||||
@ -220,6 +223,27 @@ Make sure that you specify the architecture you wish to build for in the
|
||||
"ARCHS" flag. You can specify more than one by delimiting with a space
|
||||
(e.g. "x86_64 i386").
|
||||
|
||||
### Install with vcpkg
|
||||
|
||||
```bash
|
||||
$ git clone https://github.com/microsoft/vcpkg.git
|
||||
$ ./bootstrap-vcpkg.bat # for powershell
|
||||
$ ./bootstrap-vcpkg.sh # for bash
|
||||
$ ./vcpkg install libuv
|
||||
```
|
||||
|
||||
### Install with Conan
|
||||
|
||||
You can install pre-built binaries for libuv or build it from source using [Conan](https://conan.io/). Use the following command:
|
||||
|
||||
```bash
|
||||
conan install --requires="libuv/[*]" --build=missing
|
||||
```
|
||||
|
||||
The libuv Conan recipe is kept up to date by Conan maintainers and community contributors.
|
||||
If the version is out of date, please [create an issue or pull request](https://github.com/conan-io/conan-center-index) on the ConanCenterIndex repository.
|
||||
|
||||
|
||||
### Running tests
|
||||
|
||||
Some tests are timing sensitive. Relaxing test timeouts may be necessary
|
||||
|
||||
27
SECURITY.md
Normal file
27
SECURITY.md
Normal file
@ -0,0 +1,27 @@
|
||||
# Security Policy
|
||||
|
||||
## Supported Versions
|
||||
|
||||
Currently, we are providing security updates for the latest release in the v1.x series:
|
||||
|
||||
| Version | Supported |
|
||||
| ------- | ------------------ |
|
||||
| Latest v1.x | :white_check_mark: |
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
If you believe you have found a security vulnerability in `libuv`, please use the [GitHub's private vulnerability reporting feature](https://docs.github.com/en/code-security/security-advisories/guidance-on-reporting-and-writing-information-about-vulnerabilities/privately-reporting-a-security-vulnerability#privately-reporting-a-security-vulnerability) in the [libuv repository](https://github.com/libuv/libuv) to report it to us.
|
||||
|
||||
This will allow us to assess the risk, and make a fix available before we add a bug report to the GitHub repository.
|
||||
|
||||
Please do:
|
||||
|
||||
* Provide as much information as you can about the vulnerability.
|
||||
* Provide details about your configuration and environment, if applicable.
|
||||
|
||||
Please do not:
|
||||
|
||||
* Post any information about the vulnerability in public places.
|
||||
* Attempt to exploit the vulnerability yourself.
|
||||
|
||||
We take all security bugs seriously. Thank you for improving the security of `libuv`. We appreciate your efforts and responsible disclosure and will make every effort to acknowledge your contributions.
|
||||
@ -2,17 +2,16 @@
|
||||
|
||||
| System | Support type | Supported versions | Notes |
|
||||
|---|---|---|---|
|
||||
| GNU/Linux | Tier 1 | Linux >= 2.6.32 with glibc >= 2.12 | |
|
||||
| macOS | Tier 1 | macOS >= 10.7 | |
|
||||
| Windows | Tier 1 | >= Windows 8 | VS 2015 and later are supported |
|
||||
| FreeBSD | Tier 1 | >= 10 | |
|
||||
| GNU/Linux | Tier 1 | Linux >= 3.10 with glibc >= 2.17 | |
|
||||
| macOS | Tier 1 | macOS >= 11 | Currently supported macOS releases |
|
||||
| Windows | Tier 1 | >= Windows 10 | VS 2015 and later are supported |
|
||||
| FreeBSD | Tier 2 | >= 12 | |
|
||||
| AIX | Tier 2 | >= 6 | Maintainers: @libuv/aix |
|
||||
| IBM i | Tier 2 | >= IBM i 7.2 | Maintainers: @libuv/ibmi |
|
||||
| z/OS | Tier 2 | >= V2R2 | Maintainers: @libuv/zos |
|
||||
| Linux with musl | Tier 2 | musl >= 1.0 | |
|
||||
| SmartOS | Tier 3 | >= 14.4 | |
|
||||
| Android | Tier 3 | NDK >= r15b | |
|
||||
| MinGW | Tier 3 | MinGW32 and MinGW-w64 | |
|
||||
| Android | Tier 3 | NDK >= r15b | Android 7.0, `-DANDROID_PLATFORM=android-24` |
|
||||
| MinGW | Tier 3 | MinGW-w64 | |
|
||||
| SunOS | Tier 3 | Solaris 121 and later | |
|
||||
| Other | Tier 3 | N/A | |
|
||||
|
||||
|
||||
35
autogen.sh
35
autogen.sh
@ -14,9 +14,16 @@
|
||||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
set -eu
|
||||
cd `dirname "$0"`
|
||||
|
||||
if [ "$LIBTOOLIZE" = "" ] && [ "`uname`" = "Darwin" ]; then
|
||||
if [ "${1:-dev}" = "release" ]; then
|
||||
export LIBUV_RELEASE=true
|
||||
else
|
||||
export LIBUV_RELEASE=false
|
||||
fi
|
||||
|
||||
if [ "${LIBTOOLIZE:-}" = "" ] && [ "`uname`" = "Darwin" ]; then
|
||||
LIBTOOLIZE=glibtoolize
|
||||
fi
|
||||
|
||||
@ -25,9 +32,17 @@ AUTOCONF=${AUTOCONF:-autoconf}
|
||||
AUTOMAKE=${AUTOMAKE:-automake}
|
||||
LIBTOOLIZE=${LIBTOOLIZE:-libtoolize}
|
||||
|
||||
aclocal_version=`"$ACLOCAL" --version | head -n 1 | sed 's/[^.0-9]//g'`
|
||||
autoconf_version=`"$AUTOCONF" --version | head -n 1 | sed 's/[^.0-9]//g'`
|
||||
automake_version=`"$AUTOMAKE" --version | head -n 1 | sed 's/[^.0-9]//g'`
|
||||
automake_version_major=`echo "$automake_version" | cut -d. -f1`
|
||||
automake_version_minor=`echo "$automake_version" | cut -d. -f2`
|
||||
libtoolize_version=`"$LIBTOOLIZE" --version | head -n 1 | sed 's/[^.0-9]//g'`
|
||||
|
||||
if [ $aclocal_version != $automake_version ]; then
|
||||
echo "FATAL: aclocal version appears not to be from the same as automake"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
UV_EXTRA_AUTOMAKE_FLAGS=
|
||||
if test "$automake_version_major" -gt 1 || \
|
||||
@ -39,8 +54,22 @@ fi
|
||||
echo "m4_define([UV_EXTRA_AUTOMAKE_FLAGS], [$UV_EXTRA_AUTOMAKE_FLAGS])" \
|
||||
> m4/libuv-extra-automake-flags.m4
|
||||
|
||||
set -ex
|
||||
"$LIBTOOLIZE" --copy
|
||||
(set -x
|
||||
"$LIBTOOLIZE" --copy --force
|
||||
"$ACLOCAL" -I m4
|
||||
)
|
||||
if $LIBUV_RELEASE; then
|
||||
"$AUTOCONF" -o /dev/null m4/libuv-check-versions.m4
|
||||
echo "
|
||||
AC_PREREQ($autoconf_version)
|
||||
AC_INIT([libuv-release-check], [0.0])
|
||||
AM_INIT_AUTOMAKE([$automake_version])
|
||||
LT_PREREQ($libtoolize_version)
|
||||
AC_OUTPUT
|
||||
" > m4/libuv-check-versions.m4
|
||||
fi
|
||||
(
|
||||
set -x
|
||||
"$AUTOCONF"
|
||||
"$AUTOMAKE" --add-missing --copy
|
||||
)
|
||||
|
||||
17
cmake-toolchains/cross-mingw32.cmake
Normal file
17
cmake-toolchains/cross-mingw32.cmake
Normal file
@ -0,0 +1,17 @@
|
||||
if(NOT HOST_ARCH)
|
||||
message(SEND_ERROR "-DHOST_ARCH required to be specified")
|
||||
endif()
|
||||
|
||||
list(APPEND CMAKE_TRY_COMPILE_PLATFORM_VARIABLES
|
||||
HOST_ARCH
|
||||
)
|
||||
|
||||
SET(CMAKE_SYSTEM_NAME Windows)
|
||||
set(COMPILER_PREFIX "${HOST_ARCH}-w64-mingw32")
|
||||
find_program(CMAKE_RC_COMPILER NAMES ${COMPILER_PREFIX}-windres)
|
||||
find_program(CMAKE_C_COMPILER NAMES ${COMPILER_PREFIX}-gcc)
|
||||
find_program(CMAKE_CXX_COMPILER NAMES ${COMPILER_PREFIX}-g++)
|
||||
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
||||
18
configure.ac
18
configure.ac
@ -13,12 +13,13 @@
|
||||
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
AC_PREREQ(2.57)
|
||||
AC_INIT([libuv], [1.43.0], [https://github.com/libuv/libuv/issues])
|
||||
AC_INIT([libuv], [1.50.1-dev], [https://github.com/libuv/libuv/issues])
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
m4_include([m4/libuv-extra-automake-flags.m4])
|
||||
m4_include([m4/as_case.m4])
|
||||
m4_include([m4/libuv-check-flags.m4])
|
||||
AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects] UV_EXTRA_AUTOMAKE_FLAGS)
|
||||
AM_MAINTAINER_MODE([enable]) # pass --disable-maintainer-mode if autotools may be unavailable
|
||||
AC_CANONICAL_HOST
|
||||
AC_ENABLE_SHARED
|
||||
AC_ENABLE_STATIC
|
||||
@ -28,7 +29,9 @@ AM_PROG_CC_C_O
|
||||
CC_ATTRIBUTE_VISIBILITY([default], [
|
||||
CC_FLAG_VISIBILITY([CFLAGS="${CFLAGS} -fvisibility=hidden"])
|
||||
])
|
||||
CC_CHECK_CFLAGS_APPEND([-fno-strict-aliasing])
|
||||
# Xlc has a flag "-f<filename>". Need to use CC_CHECK_FLAG_SUPPORTED_APPEND so
|
||||
# we exclude -fno-strict-aliasing for xlc
|
||||
CC_CHECK_FLAG_SUPPORTED_APPEND([-fno-strict-aliasing])
|
||||
CC_CHECK_CFLAGS_APPEND([-g])
|
||||
CC_CHECK_CFLAGS_APPEND([-std=gnu89])
|
||||
CC_CHECK_CFLAGS_APPEND([-Wall])
|
||||
@ -59,7 +62,7 @@ AM_CONDITIONAL([ANDROID], [AS_CASE([$host_os],[linux-android*],[true], [false])
|
||||
AM_CONDITIONAL([CYGWIN], [AS_CASE([$host_os],[cygwin*], [true], [false])])
|
||||
AM_CONDITIONAL([DARWIN], [AS_CASE([$host_os],[darwin*], [true], [false])])
|
||||
AM_CONDITIONAL([DRAGONFLY],[AS_CASE([$host_os],[dragonfly*], [true], [false])])
|
||||
AM_CONDITIONAL([FREEBSD], [AS_CASE([$host_os],[*freebsd*], [true], [false])])
|
||||
AM_CONDITIONAL([FREEBSD], [AS_CASE([$host_os],[freebsd*], [true], [false])])
|
||||
AM_CONDITIONAL([HAIKU], [AS_CASE([$host_os],[haiku], [true], [false])])
|
||||
AM_CONDITIONAL([HURD], [AS_CASE([$host_os],[gnu*], [true], [false])])
|
||||
AM_CONDITIONAL([LINUX], [AS_CASE([$host_os],[linux*], [true], [false])])
|
||||
@ -71,12 +74,12 @@ AM_CONDITIONAL([OS400], [AS_CASE([$host_os],[os400], [true], [false])
|
||||
AM_CONDITIONAL([SUNOS], [AS_CASE([$host_os],[solaris*], [true], [false])])
|
||||
AM_CONDITIONAL([WINNT], [AS_CASE([$host_os],[mingw*], [true], [false])])
|
||||
AS_CASE([$host_os],[mingw*], [
|
||||
LIBS="$LIBS -lws2_32 -lpsapi -liphlpapi -lshell32 -luserenv -luser32"
|
||||
LIBS="$LIBS -lws2_32 -lpsapi -liphlpapi -luserenv -luser32 -ldbghelp -lole32 -lshell32"
|
||||
])
|
||||
AS_CASE([$host_os], [solaris2.10], [
|
||||
CFLAGS="$CFLAGS -DSUNOS_NO_IFADDRS"
|
||||
])
|
||||
AS_CASE([$host_os], [netbsd*], [AC_CHECK_LIB([kvm], [kvm_open])])
|
||||
AS_CASE([$host_os], [kfreebsd*], [
|
||||
LIBS="$LIBS -lfreebsd-glue"
|
||||
])
|
||||
AS_CASE([$host_os], [haiku], [
|
||||
LIBS="$LIBS -lnetwork"
|
||||
])
|
||||
@ -85,4 +88,5 @@ AC_CONFIG_FILES([Makefile libuv.pc])
|
||||
AC_CONFIG_LINKS([test/fixtures/empty_file:test/fixtures/empty_file])
|
||||
AC_CONFIG_LINKS([test/fixtures/load_error.node:test/fixtures/load_error.node])
|
||||
AC_CONFIG_LINKS([test/fixtures/lorem_ipsum.txt:test/fixtures/lorem_ipsum.txt])
|
||||
AC_CONFIG_LINKS([test/fixtures/one_file/one_file:test/fixtures/one_file/one_file])
|
||||
AC_OUTPUT
|
||||
|
||||
3
docs/code/.gitignore
vendored
Normal file
3
docs/code/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
*/*
|
||||
!*.c
|
||||
!*.h
|
||||
51
docs/code/CMakeLists.txt
Normal file
51
docs/code/CMakeLists.txt
Normal file
@ -0,0 +1,51 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
project(libuv_sample)
|
||||
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
|
||||
add_subdirectory("../../" build)
|
||||
|
||||
set(SIMPLE_SAMPLES
|
||||
cgi
|
||||
helloworld
|
||||
dns
|
||||
detach
|
||||
default-loop
|
||||
idle-basic
|
||||
idle-compute
|
||||
interfaces
|
||||
locks
|
||||
onchange
|
||||
pipe-echo-server
|
||||
ref-timer
|
||||
spawn
|
||||
tcp-echo-server
|
||||
thread-create
|
||||
udp-dhcp
|
||||
uvcat
|
||||
uvstop
|
||||
uvtee
|
||||
)
|
||||
IF (NOT WIN32)
|
||||
list(APPEND SIMPLE_SAMPLES
|
||||
signal
|
||||
progress
|
||||
queue-cancel
|
||||
queue-work
|
||||
tty
|
||||
tty-gravity
|
||||
)
|
||||
ENDIF()
|
||||
|
||||
foreach (X IN LISTS SIMPLE_SAMPLES)
|
||||
add_executable(${X} ${X}/main.c)
|
||||
target_link_libraries(${X} uv_a)
|
||||
endforeach ()
|
||||
|
||||
|
||||
FIND_PACKAGE(CURL)
|
||||
IF(CURL_FOUND)
|
||||
add_executable(uvwget uvwget/main.c)
|
||||
target_link_libraries(uvwget uv_a ${CURL_LIBRARIES})
|
||||
ENDIF(CURL_FOUND)
|
||||
@ -15,8 +15,8 @@ void cleanup_handles(uv_process_t *req, int64_t exit_status, int term_signal) {
|
||||
}
|
||||
|
||||
void invoke_cgi_script(uv_tcp_t *client) {
|
||||
size_t size = 500;
|
||||
char path[size];
|
||||
char path[500];
|
||||
size_t size = sizeof(path);
|
||||
uv_exepath(path, &size);
|
||||
strcpy(path + (strlen(path) - strlen("cgi")), "tick");
|
||||
|
||||
|
||||
12
docs/code/default-loop/main.c
Normal file
12
docs/code/default-loop/main.c
Normal file
@ -0,0 +1,12 @@
|
||||
#include <stdio.h>
|
||||
#include <uv.h>
|
||||
|
||||
int main() {
|
||||
uv_loop_t *loop = uv_default_loop();
|
||||
|
||||
printf("Default loop.\n");
|
||||
uv_run(loop, UV_RUN_DEFAULT);
|
||||
|
||||
uv_loop_close(loop);
|
||||
return 0;
|
||||
}
|
||||
@ -11,17 +11,17 @@ int main() {
|
||||
|
||||
printf("Number of interfaces: %d\n", count);
|
||||
while (i--) {
|
||||
uv_interface_address_t interface = info[i];
|
||||
uv_interface_address_t interface_a = info[i];
|
||||
|
||||
printf("Name: %s\n", interface.name);
|
||||
printf("Internal? %s\n", interface.is_internal ? "Yes" : "No");
|
||||
printf("Name: %s\n", interface_a.name);
|
||||
printf("Internal? %s\n", interface_a.is_internal ? "Yes" : "No");
|
||||
|
||||
if (interface.address.address4.sin_family == AF_INET) {
|
||||
uv_ip4_name(&interface.address.address4, buf, sizeof(buf));
|
||||
if (interface_a.address.address4.sin_family == AF_INET) {
|
||||
uv_ip4_name(&interface_a.address.address4, buf, sizeof(buf));
|
||||
printf("IPv4 address: %s\n", buf);
|
||||
}
|
||||
else if (interface.address.address4.sin_family == AF_INET6) {
|
||||
uv_ip6_name(&interface.address.address6, buf, sizeof(buf));
|
||||
else if (interface_a.address.address4.sin_family == AF_INET6) {
|
||||
uv_ip6_name(&interface_a.address.address6, buf, sizeof(buf));
|
||||
printf("IPv6 address: %s\n", buf);
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <uv.h>
|
||||
|
||||
@ -7,7 +6,7 @@ void hare(void *arg) {
|
||||
int tracklen = *((int *) arg);
|
||||
while (tracklen) {
|
||||
tracklen--;
|
||||
sleep(1);
|
||||
uv_sleep(1000);
|
||||
fprintf(stderr, "Hare ran another step\n");
|
||||
}
|
||||
fprintf(stderr, "Hare done running!\n");
|
||||
@ -18,7 +17,7 @@ void tortoise(void *arg) {
|
||||
while (tracklen) {
|
||||
tracklen--;
|
||||
fprintf(stderr, "Tortoise ran another step\n");
|
||||
sleep(3);
|
||||
uv_sleep(3000);
|
||||
}
|
||||
fprintf(stderr, "Tortoise done running!\n");
|
||||
}
|
||||
|
||||
@ -5,25 +5,27 @@
|
||||
|
||||
uv_loop_t *loop;
|
||||
uv_tty_t tty;
|
||||
int main() {
|
||||
loop = uv_default_loop();
|
||||
|
||||
int main() {
|
||||
uv_write_t req;
|
||||
uv_buf_t buf;
|
||||
uv_write_t req1;
|
||||
uv_buf_t buf1;
|
||||
|
||||
loop = uv_default_loop();
|
||||
uv_tty_init(loop, &tty, STDOUT_FILENO, 0);
|
||||
uv_tty_set_mode(&tty, UV_TTY_MODE_NORMAL);
|
||||
|
||||
if (uv_guess_handle(1) == UV_TTY) {
|
||||
uv_write_t req;
|
||||
uv_buf_t buf;
|
||||
buf.base = "\033[41;37m";
|
||||
buf.len = strlen(buf.base);
|
||||
uv_write(&req, (uv_stream_t*) &tty, &buf, 1, NULL);
|
||||
buf1.base = "\033[41;37m";
|
||||
buf1.len = strlen(buf1.base);
|
||||
uv_write(&req1, (uv_stream_t*) &tty, &buf1, 1, NULL);
|
||||
}
|
||||
|
||||
uv_write_t req;
|
||||
uv_buf_t buf;
|
||||
buf.base = "Hello TTY\n";
|
||||
buf.len = strlen(buf.base);
|
||||
uv_write(&req, (uv_stream_t*) &tty, &buf, 1, NULL);
|
||||
|
||||
uv_tty_reset_mode();
|
||||
return uv_run(loop, UV_RUN_DEFAULT);
|
||||
}
|
||||
|
||||
@ -53,7 +53,8 @@ uv_buf_t make_discover_msg() {
|
||||
// HOPS
|
||||
buffer.base[3] = 0x0;
|
||||
// XID 4 bytes
|
||||
buffer.base[4] = (unsigned int) random();
|
||||
if (uv_random(NULL, NULL, &buffer.base[4], 4, 0, NULL))
|
||||
abort();
|
||||
// SECS
|
||||
buffer.base[8] = 0x0;
|
||||
// FLAGS
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <uv.h>
|
||||
|
||||
void on_read(uv_fs_t *req);
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
@ -1,42 +1,36 @@
|
||||
# primary
|
||||
Sphinx==3.5.4
|
||||
furo==2023.5.20
|
||||
Sphinx==6.1.3
|
||||
|
||||
# dependencies
|
||||
alabaster==0.7.12
|
||||
appdirs==1.4.3
|
||||
Babel==2.9.0
|
||||
CacheControl==0.12.6
|
||||
certifi==2019.11.28
|
||||
chardet==3.0.4
|
||||
colorama==0.4.3
|
||||
contextlib2==0.6.0
|
||||
distlib==0.3.0
|
||||
distro==1.4.0
|
||||
docutils==0.16
|
||||
html5lib==1.0.1
|
||||
idna==2.8
|
||||
imagesize==1.2.0
|
||||
ipaddr==2.2.0
|
||||
Jinja2==2.11.3
|
||||
lockfile==0.12.2
|
||||
MarkupSafe==1.1.1
|
||||
msgpack==0.6.2
|
||||
packaging==20.3
|
||||
pep517==0.8.2
|
||||
progress==1.5
|
||||
Pygments==2.8.1
|
||||
pyparsing==2.4.6
|
||||
pytoml==0.1.21
|
||||
pytz==2021.1
|
||||
requests==2.22.0
|
||||
retrying==1.3.3
|
||||
six==1.14.0
|
||||
snowballstemmer==2.1.0
|
||||
sphinxcontrib-applehelp==1.0.2
|
||||
alabaster==0.7.13
|
||||
Babel==2.11.0
|
||||
beautifulsoup4==4.12.2
|
||||
certifi==2022.12.7
|
||||
charset-normalizer==3.0.1
|
||||
colorama==0.4.6
|
||||
docutils==0.19
|
||||
idna==3.4
|
||||
imagesize==1.4.1
|
||||
importlib-metadata==6.0.0
|
||||
Jinja2==3.1.2
|
||||
livereload==2.6.3
|
||||
MarkupSafe==2.1.2
|
||||
packaging==23.0
|
||||
Pygments==2.14.0
|
||||
pytz==2022.7.1
|
||||
requests==2.28.2
|
||||
six==1.16.0
|
||||
snowballstemmer==2.2.0
|
||||
soupsieve==2.4.1
|
||||
sphinx-autobuild==2021.3.14
|
||||
sphinx-basic-ng==1.0.0b2
|
||||
sphinxcontrib-devhelp==1.0.2
|
||||
sphinxcontrib-htmlhelp==1.0.3
|
||||
sphinxcontrib-htmlhelp==2.0.0
|
||||
sphinxcontrib-jsmath==1.0.1
|
||||
sphinxcontrib-qthelp==1.0.3
|
||||
sphinxcontrib-serializinghtml==1.1.4
|
||||
urllib3==1.25.8
|
||||
webencodings==0.5.1
|
||||
sphinxcontrib-serializinghtml==1.1.5
|
||||
sphinxcontrib.applehelp==1.0.3
|
||||
tornado==6.3.2
|
||||
urllib3==1.26.14
|
||||
zipp==3.11.0
|
||||
|
||||
@ -118,7 +118,7 @@ pygments_style = 'sphinx'
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
html_theme = 'nature'
|
||||
html_theme = 'furo'
|
||||
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
|
||||
@ -60,16 +60,15 @@ stages of a loop iteration:
|
||||
:align: center
|
||||
|
||||
|
||||
#. The loop concept of 'now' is updated. The event loop caches the current time at the start of
|
||||
the event loop tick in order to reduce the number of time-related system calls.
|
||||
#. The loop concept of 'now' is initially set.
|
||||
|
||||
#. Due timers are run if the loop was run with ``UV_RUN_DEFAULT``. All active timers scheduled
|
||||
for a time before the loop's concept of *now* get their callbacks called.
|
||||
|
||||
#. If the loop is *alive* an iteration is started, otherwise the loop will exit immediately. So,
|
||||
when is a loop considered to be *alive*? If a loop has active and ref'd handles, active
|
||||
requests or closing handles it's considered to be *alive*.
|
||||
|
||||
#. Due timers are run. All active timers scheduled for a time before the loop's concept of *now*
|
||||
get their callbacks called.
|
||||
|
||||
#. Pending callbacks are called. All I/O callbacks are called right after polling for I/O, for the
|
||||
most part. There are cases, however, in which calling such a callback is deferred for the next
|
||||
loop iteration. If the previous iteration deferred any I/O callback it will be run at this point.
|
||||
@ -101,9 +100,11 @@ stages of a loop iteration:
|
||||
#. Close callbacks are called. If a handle was closed by calling :c:func:`uv_close` it will
|
||||
get the close callback called.
|
||||
|
||||
#. Special case in case the loop was run with ``UV_RUN_ONCE``, as it implies forward progress.
|
||||
It's possible that no I/O callbacks were fired after blocking for I/O, but some time has passed
|
||||
so there might be timers which are due, those timers get their callbacks called.
|
||||
#. The loop concept of 'now' is updated.
|
||||
|
||||
#. Due timers are run. Note that 'now' is not updated again until the next loop iteration.
|
||||
So if a timer became due while other timers were being processed, it won't be run until
|
||||
the following event loop iteration.
|
||||
|
||||
#. Iteration ends. If the loop was run with ``UV_RUN_NOWAIT`` or ``UV_RUN_ONCE`` modes the
|
||||
iteration ends and :c:func:`uv_run` will return. If the loop was run with ``UV_RUN_DEFAULT``
|
||||
|
||||
@ -339,6 +339,9 @@ Error constants
|
||||
|
||||
socket type not supported
|
||||
|
||||
.. c:macro:: UV_EUNATCH
|
||||
|
||||
protocol driver not attached
|
||||
|
||||
API
|
||||
---
|
||||
|
||||
@ -12,6 +12,15 @@ otherwise it will be performed asynchronously.
|
||||
All file operations are run on the threadpool. See :ref:`threadpool` for information
|
||||
on the threadpool size.
|
||||
|
||||
Starting with libuv v1.45.0, some file operations on Linux are handed off to
|
||||
`io_uring <https://en.wikipedia.org/wiki/Io_uring>` when possible. Apart from
|
||||
a (sometimes significant) increase in throughput there should be no change in
|
||||
observable behavior. Libuv reverts to using its threadpool when the necessary
|
||||
kernel features are unavailable or unsuitable. Starting with libuv v1.49.0 this
|
||||
behavior was reverted and Libuv on Linux by default will be using the threadpool
|
||||
again. In order to enable io_uring the :c:type:`uv_loop_t` instance must be
|
||||
configured with the :c:type:`UV_LOOP_ENABLE_IO_URING_SQPOLL` option.
|
||||
|
||||
.. note::
|
||||
On Windows `uv_fs_*` functions use utf-8 encoding.
|
||||
|
||||
@ -24,7 +33,8 @@ Data types
|
||||
|
||||
.. c:type:: uv_timespec_t
|
||||
|
||||
Portable equivalent of ``struct timespec``.
|
||||
Y2K38-unsafe data type for storing times with nanosecond resolution.
|
||||
Will be replaced with :c:type:`uv_timespec64_t` in libuv v2.0.
|
||||
|
||||
::
|
||||
|
||||
@ -122,10 +132,9 @@ Data types
|
||||
uint64_t f_spare[4];
|
||||
} uv_statfs_t;
|
||||
|
||||
.. c:enum:: uv_dirent_t
|
||||
.. c:enum:: uv_dirent_type_t
|
||||
|
||||
Cross platform (reduced) equivalent of ``struct dirent``.
|
||||
Used in :c:func:`uv_fs_scandir_next`.
|
||||
Type of dirent.
|
||||
|
||||
::
|
||||
|
||||
@ -140,6 +149,14 @@ Data types
|
||||
UV_DIRENT_BLOCK
|
||||
} uv_dirent_type_t;
|
||||
|
||||
|
||||
.. c:type:: uv_dirent_t
|
||||
|
||||
Cross platform (reduced) equivalent of ``struct dirent``.
|
||||
Used in :c:func:`uv_fs_scandir_next`.
|
||||
|
||||
::
|
||||
|
||||
typedef struct uv_dirent_s {
|
||||
const char* name;
|
||||
uv_dirent_type_t type;
|
||||
@ -160,6 +177,10 @@ Data types
|
||||
size_t nentries;
|
||||
} uv_dir_t;
|
||||
|
||||
.. c:type:: void (*uv_fs_cb)(uv_fs_t* req)
|
||||
|
||||
Callback called when a request is completed asynchronously.
|
||||
|
||||
|
||||
Public members
|
||||
^^^^^^^^^^^^^^
|
||||
@ -218,7 +239,8 @@ API
|
||||
|
||||
.. c:function:: int uv_fs_read(uv_loop_t* loop, uv_fs_t* req, uv_file file, const uv_buf_t bufs[], unsigned int nbufs, int64_t offset, uv_fs_cb cb)
|
||||
|
||||
Equivalent to :man:`preadv(2)`.
|
||||
Equivalent to :man:`preadv(2)`. If the `offset` argument is `-1`, then
|
||||
the current file offset is used and updated.
|
||||
|
||||
.. warning::
|
||||
On Windows, under non-MSVC environments (e.g. when GCC or Clang is used
|
||||
@ -231,7 +253,8 @@ API
|
||||
|
||||
.. c:function:: int uv_fs_write(uv_loop_t* loop, uv_fs_t* req, uv_file file, const uv_buf_t bufs[], unsigned int nbufs, int64_t offset, uv_fs_cb cb)
|
||||
|
||||
Equivalent to :man:`pwritev(2)`.
|
||||
Equivalent to :man:`pwritev(2)`. If the `offset` argument is `-1`, then
|
||||
the current file offset is used and updated.
|
||||
|
||||
.. warning::
|
||||
On Windows, under non-MSVC environments (e.g. when GCC or Clang is used
|
||||
@ -407,6 +430,12 @@ API
|
||||
|
||||
Equivalent to :man:`utime(2)`, :man:`futimes(3)` and :man:`lutimes(3)` respectively.
|
||||
|
||||
Passing `UV_FS_UTIME_NOW` as the atime or mtime sets the timestamp to the
|
||||
current time.
|
||||
|
||||
Passing `UV_FS_UTIME_OMIT` as the atime or mtime leaves the timestamp
|
||||
untouched.
|
||||
|
||||
.. note::
|
||||
z/OS: `uv_fs_lutime()` is not implemented for z/OS. It can still be called but will return
|
||||
``UV_ENOSYS``.
|
||||
@ -441,7 +470,7 @@ API
|
||||
|
||||
.. c:function:: int uv_fs_realpath(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb)
|
||||
|
||||
Equivalent to :man:`realpath(3)` on Unix. Windows uses `GetFinalPathNameByHandle <https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfinalpathnamebyhandlea>`_.
|
||||
Equivalent to :man:`realpath(3)` on Unix. Windows uses `GetFinalPathNameByHandleW <https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfinalpathnamebyhandlew>`_.
|
||||
The resulting string is stored in `req->ptr`.
|
||||
|
||||
.. warning::
|
||||
@ -463,10 +492,6 @@ API
|
||||
The background story and some more details on these issues can be checked
|
||||
`here <https://github.com/nodejs/node/issues/7726>`_.
|
||||
|
||||
.. note::
|
||||
This function is not implemented on Windows XP and Windows Server 2003.
|
||||
On these systems, UV_ENOSYS is returned.
|
||||
|
||||
.. versionadded:: 1.8.0
|
||||
|
||||
.. c:function:: int uv_fs_chown(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_uid_t uid, uv_gid_t gid, uv_fs_cb cb)
|
||||
@ -644,7 +669,7 @@ File open constants
|
||||
|
||||
.. note::
|
||||
`UV_FS_O_RANDOM` is only supported on Windows via
|
||||
`FILE_FLAG_RANDOM_ACCESS <https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea>`_.
|
||||
`FILE_FLAG_RANDOM_ACCESS <https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilew>`_.
|
||||
|
||||
.. c:macro:: UV_FS_O_RDONLY
|
||||
|
||||
@ -661,7 +686,7 @@ File open constants
|
||||
|
||||
.. note::
|
||||
`UV_FS_O_SEQUENTIAL` is only supported on Windows via
|
||||
`FILE_FLAG_SEQUENTIAL_SCAN <https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea>`_.
|
||||
`FILE_FLAG_SEQUENTIAL_SCAN <https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilew>`_.
|
||||
|
||||
.. c:macro:: UV_FS_O_SHORT_LIVED
|
||||
|
||||
@ -669,7 +694,7 @@ File open constants
|
||||
|
||||
.. note::
|
||||
`UV_FS_O_SHORT_LIVED` is only supported on Windows via
|
||||
`FILE_ATTRIBUTE_TEMPORARY <https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea>`_.
|
||||
`FILE_ATTRIBUTE_TEMPORARY <https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilew>`_.
|
||||
|
||||
.. c:macro:: UV_FS_O_SYMLINK
|
||||
|
||||
@ -690,7 +715,7 @@ File open constants
|
||||
|
||||
.. note::
|
||||
`UV_FS_O_TEMPORARY` is only supported on Windows via
|
||||
`FILE_ATTRIBUTE_TEMPORARY <https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea>`_.
|
||||
`FILE_ATTRIBUTE_TEMPORARY <https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilew>`_.
|
||||
|
||||
.. c:macro:: UV_FS_O_TRUNC
|
||||
|
||||
|
||||
@ -39,11 +39,20 @@ Data types
|
||||
.. c:type:: void (*uv_fs_event_cb)(uv_fs_event_t* handle, const char* filename, int events, int status)
|
||||
|
||||
Callback passed to :c:func:`uv_fs_event_start` which will be called repeatedly
|
||||
after the handle is started. If the handle was started with a directory the
|
||||
`filename` parameter will be a relative path to a file contained in the directory.
|
||||
The `events` parameter is an ORed mask of :c:type:`uv_fs_event` elements.
|
||||
after the handle is started.
|
||||
|
||||
.. c:type:: uv_fs_event
|
||||
If the handle was started with a directory the `filename` parameter will
|
||||
be a relative path to a file contained in the directory, or `NULL` if the
|
||||
file name cannot be determined.
|
||||
|
||||
The `events` parameter is an ORed mask of :c:enum:`uv_fs_event` elements.
|
||||
|
||||
.. note::
|
||||
For FreeBSD path could sometimes be `NULL` due to a kernel bug.
|
||||
|
||||
.. _Reference: https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=197695
|
||||
|
||||
.. c:enum:: uv_fs_event
|
||||
|
||||
Event types that :c:type:`uv_fs_event_t` handles monitor.
|
||||
|
||||
@ -54,7 +63,7 @@ Data types
|
||||
UV_CHANGE = 2
|
||||
};
|
||||
|
||||
.. c:type:: uv_fs_event_flags
|
||||
.. c:enum:: uv_fs_event_flags
|
||||
|
||||
Flags that can be passed to :c:func:`uv_fs_event_start` to control its
|
||||
behavior.
|
||||
@ -105,10 +114,13 @@ API
|
||||
.. c:function:: int uv_fs_event_start(uv_fs_event_t* handle, uv_fs_event_cb cb, const char* path, unsigned int flags)
|
||||
|
||||
Start the handle with the given callback, which will watch the specified
|
||||
`path` for changes. `flags` can be an ORed mask of :c:type:`uv_fs_event_flags`.
|
||||
`path` for changes. `flags` can be an ORed mask of :c:enum:`uv_fs_event_flags`.
|
||||
|
||||
.. note:: Currently the only supported flag is ``UV_FS_EVENT_RECURSIVE`` and
|
||||
only on OSX and Windows.
|
||||
.. note:: On macOS, events collected by the OS immediately before calling
|
||||
``uv_fs_event_start`` might be reported to the `uv_fs_event_cb`
|
||||
callback.
|
||||
|
||||
.. c:function:: int uv_fs_event_stop(uv_fs_event_t* handle)
|
||||
|
||||
|
||||
@ -71,7 +71,7 @@ architecture of libuv and its background. If you have no prior experience with
|
||||
either libuv or libev, it is a quick, useful watch.
|
||||
|
||||
libuv's event loop is explained in more detail in the `documentation
|
||||
<http://docs.libuv.org/en/v1.x/design.html#the-i-o-loop>`_.
|
||||
<https://docs.libuv.org/en/v1.x/design.html#the-i-o-loop>`_.
|
||||
|
||||
.. raw:: html
|
||||
|
||||
@ -109,6 +109,11 @@ A default loop is provided by libuv and can be accessed using
|
||||
``uv_default_loop()``. You should use this loop if you only want a single
|
||||
loop.
|
||||
|
||||
.. rubric:: default-loop/main.c
|
||||
.. literalinclude:: ../../code/default-loop/main.c
|
||||
:language: c
|
||||
:linenos:
|
||||
|
||||
.. note::
|
||||
|
||||
node.js uses the default loop as its main loop. If you are writing bindings
|
||||
@ -121,7 +126,7 @@ Error handling
|
||||
|
||||
Initialization functions or synchronous functions which may fail return a negative number on error. Async functions that may fail will pass a status parameter to their callbacks. The error messages are defined as ``UV_E*`` `constants`_.
|
||||
|
||||
.. _constants: http://docs.libuv.org/en/v1.x/errors.html#error-constants
|
||||
.. _constants: https://docs.libuv.org/en/v1.x/errors.html#error-constants
|
||||
|
||||
You can use the ``uv_strerror(int)`` and ``uv_err_name(int)`` functions
|
||||
to get a ``const char *`` describing the error or the error name respectively.
|
||||
@ -169,6 +174,16 @@ handle is used for.
|
||||
typedef struct uv_udp_send_s uv_udp_send_t;
|
||||
typedef struct uv_fs_s uv_fs_t;
|
||||
typedef struct uv_work_s uv_work_t;
|
||||
typedef struct uv_random_s uv_random_t;
|
||||
|
||||
/* None of the above. */
|
||||
typedef struct uv_env_item_s uv_env_item_t;
|
||||
typedef struct uv_cpu_info_s uv_cpu_info_t;
|
||||
typedef struct uv_interface_address_s uv_interface_address_t;
|
||||
typedef struct uv_dirent_s uv_dirent_t;
|
||||
typedef struct uv_passwd_s uv_passwd_t;
|
||||
typedef struct uv_utsname_s uv_utsname_t;
|
||||
typedef struct uv_statfs_s uv_statfs_t;
|
||||
|
||||
|
||||
Handles represent long-lived objects. Async operations on such handles are
|
||||
|
||||
@ -13,7 +13,7 @@ Simple filesystem read/write is achieved using the ``uv_fs_*`` functions and the
|
||||
watchers registered with the event loop when application interaction is
|
||||
required.
|
||||
|
||||
.. _thread pool: http://docs.libuv.org/en/v1.x/threadpool.html#thread-pool-work-scheduling
|
||||
.. _thread pool: https://docs.libuv.org/en/v1.x/threadpool.html#thread-pool-work-scheduling
|
||||
|
||||
All filesystem functions have two forms - *synchronous* and *asynchronous*.
|
||||
|
||||
@ -66,7 +66,7 @@ The ``result`` field of a ``uv_fs_t`` is the file descriptor in case of the
|
||||
.. literalinclude:: ../../code/uvcat/main.c
|
||||
:language: c
|
||||
:linenos:
|
||||
:lines: 26-40
|
||||
:lines: 26-39
|
||||
:emphasize-lines: 2,8,12
|
||||
|
||||
In the case of a read call, you should pass an *initialized* buffer which will
|
||||
@ -91,7 +91,7 @@ callbacks.
|
||||
.. literalinclude:: ../../code/uvcat/main.c
|
||||
:language: c
|
||||
:linenos:
|
||||
:lines: 16-24
|
||||
:lines: 17-24
|
||||
:emphasize-lines: 6
|
||||
|
||||
.. warning::
|
||||
@ -132,6 +132,7 @@ same patterns as the read/write/open calls, returning the result in the
|
||||
int uv_fs_copyfile(uv_loop_t* loop, uv_fs_t* req, const char* path, const char* new_path, int flags, uv_fs_cb cb);
|
||||
int uv_fs_mkdir(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode, uv_fs_cb cb);
|
||||
int uv_fs_mkdtemp(uv_loop_t* loop, uv_fs_t* req, const char* tpl, uv_fs_cb cb);
|
||||
int uv_fs_mkstemp(uv_loop_t* loop, uv_fs_t* req, const char* tpl, uv_fs_cb cb);
|
||||
int uv_fs_rmdir(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb);
|
||||
int uv_fs_scandir(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, uv_fs_cb cb);
|
||||
int uv_fs_scandir_next(uv_fs_t* req, uv_dirent_t* ent);
|
||||
@ -149,6 +150,7 @@ same patterns as the read/write/open calls, returning the result in the
|
||||
int uv_fs_chmod(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode, uv_fs_cb cb);
|
||||
int uv_fs_utime(uv_loop_t* loop, uv_fs_t* req, const char* path, double atime, double mtime, uv_fs_cb cb);
|
||||
int uv_fs_futime(uv_loop_t* loop, uv_fs_t* req, uv_file file, double atime, double mtime, uv_fs_cb cb);
|
||||
int uv_fs_lutime(uv_loop_t* loop, uv_fs_t* req, const char* path, double atime, double mtime, uv_fs_cb cb);
|
||||
int uv_fs_lstat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb);
|
||||
int uv_fs_link(uv_loop_t* loop, uv_fs_t* req, const char* path, const char* new_path, uv_fs_cb cb);
|
||||
int uv_fs_symlink(uv_loop_t* loop, uv_fs_t* req, const char* path, const char* new_path, int flags, uv_fs_cb cb);
|
||||
@ -158,6 +160,7 @@ same patterns as the read/write/open calls, returning the result in the
|
||||
int uv_fs_chown(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_uid_t uid, uv_gid_t gid, uv_fs_cb cb);
|
||||
int uv_fs_fchown(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_uid_t uid, uv_gid_t gid, uv_fs_cb cb);
|
||||
int uv_fs_lchown(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_uid_t uid, uv_gid_t gid, uv_fs_cb cb);
|
||||
int uv_fs_statfs(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb);
|
||||
|
||||
|
||||
.. _buffers-and-streams:
|
||||
@ -190,7 +193,7 @@ and freed by the application.
|
||||
|
||||
.. ERROR::
|
||||
|
||||
THIS PROGRAM DOES NOT ALWAYS WORK, NEED SOMETHING BETTER**
|
||||
**THIS PROGRAM DOES NOT ALWAYS WORK, NEED SOMETHING BETTER**
|
||||
|
||||
To demonstrate streams we will need to use ``uv_pipe_t``. This allows streaming
|
||||
local files [#]_. Here is a simple tee utility using libuv. Doing all operations
|
||||
@ -209,7 +212,7 @@ opened as bidirectional by default.
|
||||
.. literalinclude:: ../../code/uvtee/main.c
|
||||
:language: c
|
||||
:linenos:
|
||||
:lines: 61-80
|
||||
:lines: 62-80
|
||||
:emphasize-lines: 4,5,15
|
||||
|
||||
The third argument of ``uv_pipe_init()`` should be set to 1 for IPC using named
|
||||
@ -285,6 +288,13 @@ a command whenever any of the watched files change::
|
||||
|
||||
./onchange <command> <file1> [file2] ...
|
||||
|
||||
.. note::
|
||||
|
||||
Currently this example only works on OSX and Windows.
|
||||
Refer to the `notes of uv_fs_event_start`_ function.
|
||||
|
||||
.. _notes of uv_fs_event_start: https://docs.libuv.org/en/v1.x/fs_event.html#c.uv_fs_event_start
|
||||
|
||||
The file change notification is started using ``uv_fs_event_init()``:
|
||||
|
||||
.. rubric:: onchange/main.c - The setup
|
||||
@ -319,9 +329,9 @@ The callback will receive the following arguments:
|
||||
#. ``const char *filename`` - If a directory is being monitored, this is the
|
||||
file which was changed. Only non-``null`` on Linux and Windows. May be ``null``
|
||||
even on those platforms.
|
||||
#. ``int flags`` - one of ``UV_RENAME`` or ``UV_CHANGE``, or a bitwise OR of
|
||||
#. ``int events`` - one of ``UV_RENAME`` or ``UV_CHANGE``, or a bitwise OR of
|
||||
both.
|
||||
#. ``int status`` - Currently 0.
|
||||
#. ``int status`` - If ``status < 0``, there is an :ref:`libuv error<libuv-error-handling>`.
|
||||
|
||||
In our example we simply print the arguments and run the command using
|
||||
``system()``.
|
||||
|
||||
@ -8,7 +8,7 @@ It is meant to cover the main areas of libuv, but is not a comprehensive
|
||||
reference discussing every function and data structure. The `official libuv
|
||||
documentation`_ may be consulted for full details.
|
||||
|
||||
.. _official libuv documentation: http://docs.libuv.org/en/v1.x/
|
||||
.. _official libuv documentation: https://docs.libuv.org/en/v1.x/
|
||||
|
||||
This book is still a work in progress, so sections may be incomplete, but
|
||||
I hope you will enjoy it as it grows.
|
||||
@ -47,25 +47,23 @@ Since then libuv has continued to mature and become a high quality standalone
|
||||
library for system programming. Users outside of node.js include Mozilla's
|
||||
Rust_ programming language, and a variety_ of language bindings.
|
||||
|
||||
This book and the code is based on libuv version `v1.3.0`_.
|
||||
This book and the code is based on libuv version `v1.42.0`_.
|
||||
|
||||
Code
|
||||
----
|
||||
|
||||
All the code from this book is included as part of the source of the book on
|
||||
Github. `Clone`_/`Download`_ the book, then build libuv::
|
||||
All the example code and the source of the book is included as part of
|
||||
the libuv_ project on GitHub.
|
||||
Clone or Download libuv_, then build it::
|
||||
|
||||
cd libuv
|
||||
./autogen.sh
|
||||
sh autogen.sh
|
||||
./configure
|
||||
make
|
||||
|
||||
There is no need to ``make install``. To build the examples run ``make`` in the
|
||||
``code/`` directory.
|
||||
``docs/code/`` directory.
|
||||
|
||||
.. _Clone: https://github.com/nikhilm/uvbook
|
||||
.. _Download: https://github.com/nikhilm/uvbook/downloads
|
||||
.. _v1.3.0: https://github.com/libuv/libuv/tags
|
||||
.. _v1.42.0: https://github.com/libuv/libuv/releases/tag/v1.42.0
|
||||
.. _V8: https://v8.dev
|
||||
.. _libev: http://software.schmorp.de/pkg/libev.html
|
||||
.. _libuv: https://github.com/libuv/libuv
|
||||
|
||||
@ -164,7 +164,7 @@ IPv6 stack only
|
||||
|
||||
IPv6 sockets can be used for both IPv4 and IPv6 communication. If you want to
|
||||
restrict the socket to IPv6 only, pass the ``UV_UDP_IPV6ONLY`` flag to
|
||||
``uv_udp_bind`` [#]_.
|
||||
``uv_udp_bind``.
|
||||
|
||||
Multicast
|
||||
~~~~~~~~~
|
||||
@ -250,7 +250,6 @@ times, with each address being reported once.
|
||||
----
|
||||
|
||||
.. [#] https://beej.us/guide/bgnet/html/#broadcast-packetshello-world
|
||||
.. [#] on Windows only supported on Windows Vista and later.
|
||||
.. [#] https://www.tldp.org/HOWTO/Multicast-HOWTO-6.html#ss6.1
|
||||
.. [#] libuv use the system ``getaddrinfo`` in the libuv threadpool. libuv
|
||||
v0.8.0 and earlier also included c-ares_ as an alternative, but this has been
|
||||
|
||||
@ -53,6 +53,8 @@ ID of the child process.
|
||||
The exit callback will be invoked with the *exit status* and the type of *signal*
|
||||
which caused the exit.
|
||||
|
||||
Note that it is important **not** to call ``uv_close`` before the exit callback.
|
||||
|
||||
.. rubric:: spawn/main.c
|
||||
.. literalinclude:: ../../code/spawn/main.c
|
||||
:language: c
|
||||
@ -126,7 +128,8 @@ of ``uv_kill`` is::
|
||||
|
||||
For processes started using libuv, you may use ``uv_process_kill`` instead,
|
||||
which accepts the ``uv_process_t`` watcher as the first argument, rather than
|
||||
the pid. In this case, **remember to call** ``uv_close`` on the watcher.
|
||||
the pid. In this case, **remember to call** ``uv_close`` on the watcher _after_
|
||||
the exit callback has been called.
|
||||
|
||||
Signals
|
||||
-------
|
||||
@ -330,7 +333,7 @@ to hand off their I/O to other processes. Applications include load-balancing
|
||||
servers, worker processes and other ways to make optimum use of CPU. libuv only
|
||||
supports sending **TCP sockets or other pipes** over pipes for now.
|
||||
|
||||
To demonstrate, we will look at a echo server implementation that hands of
|
||||
To demonstrate, we will look at an echo server implementation that hands off
|
||||
clients to worker processes in a round-robin fashion. This program is a bit
|
||||
involved, and while only snippets are included in the book, it is recommended
|
||||
to read the full code to really understand it.
|
||||
|
||||
@ -220,7 +220,7 @@ progress with the download whenever libuv notifies of I/O readiness.
|
||||
.. literalinclude:: ../../code/uvwget/main.c
|
||||
:language: c
|
||||
:linenos:
|
||||
:lines: 1-9,140-
|
||||
:lines: 1-9,142-
|
||||
:emphasize-lines: 7,21,24-25
|
||||
|
||||
The way each library is integrated with libuv will vary. In the case of
|
||||
@ -235,7 +235,7 @@ Our downloader is to be invoked as::
|
||||
|
||||
$ ./uvwget [url1] [url2] ...
|
||||
|
||||
So we add each argument as an URL
|
||||
So we add each argument as a URL
|
||||
|
||||
.. rubric:: uvwget/main.c - Adding urls
|
||||
.. literalinclude:: ../../code/uvwget/main.c
|
||||
@ -363,7 +363,7 @@ to get the error message.
|
||||
argument. ``init_plugin_function`` is a function pointer to the sort of
|
||||
function we are looking for in the application's plugins.
|
||||
|
||||
.. _shared libraries: https://en.wikipedia.org/wiki/Shared_library#Shared_libraries
|
||||
.. _shared libraries: https://en.wikipedia.org/wiki/Shared_library
|
||||
|
||||
TTY
|
||||
---
|
||||
|
||||
@ -94,7 +94,7 @@ Public members
|
||||
|
||||
.. c:member:: uv_handle_type uv_handle_t.type
|
||||
|
||||
The :c:type:`uv_handle_type`, indicating the type of the underlying handle. Readonly.
|
||||
The :c:enum:`uv_handle_type`, indicating the type of the underlying handle. Readonly.
|
||||
|
||||
.. c:member:: void* uv_handle_t.data
|
||||
|
||||
@ -153,6 +153,9 @@ API
|
||||
In-progress requests, like uv_connect_t or uv_write_t, are cancelled and
|
||||
have their callbacks called asynchronously with status=UV_ECANCELED.
|
||||
|
||||
`close_cb` can be `NULL` in cases where no cleanup or deallocation is
|
||||
necessary.
|
||||
|
||||
.. c:function:: void uv_ref(uv_handle_t* handle)
|
||||
|
||||
Reference the given handle. References are idempotent, that is, if a handle
|
||||
@ -245,7 +248,7 @@ just for some handle types.
|
||||
|
||||
.. versionadded:: 1.19.0
|
||||
|
||||
.. c:function:: void* uv_handle_set_data(uv_handle_t* handle, void* data)
|
||||
.. c:function:: void uv_handle_set_data(uv_handle_t* handle, void* data)
|
||||
|
||||
Sets `handle->data` to `data`.
|
||||
|
||||
|
||||
@ -58,5 +58,5 @@ libuv can be downloaded from `here <https://dist.libuv.org/dist/>`_.
|
||||
Installation
|
||||
------------
|
||||
|
||||
Installation instructions can be found in `the README <https://github.com/libuv/libuv/blob/master/README.md>`_.
|
||||
Installation instructions can be found in the `README <https://github.com/libuv/libuv/blob/master/README.md>`_.
|
||||
|
||||
|
||||
@ -16,6 +16,19 @@ Data types
|
||||
|
||||
Loop data type.
|
||||
|
||||
.. c:enum:: uv_loop_option
|
||||
|
||||
Additional loop options.
|
||||
See :c:func:`uv_loop_configure`.
|
||||
|
||||
::
|
||||
|
||||
typedef enum {
|
||||
UV_LOOP_BLOCK_SIGNAL = 0,
|
||||
UV_METRICS_IDLE_TIME,
|
||||
UV_LOOP_USE_IO_URING_SQPOLL
|
||||
} uv_loop_option;
|
||||
|
||||
.. c:enum:: uv_run_mode
|
||||
|
||||
Mode used to run the loop with :c:func:`uv_run`.
|
||||
@ -73,8 +86,13 @@ API
|
||||
|
||||
This option is necessary to use :c:func:`uv_metrics_idle_time`.
|
||||
|
||||
- UV_LOOP_ENABLE_IO_URING_SQPOLL: Enable SQPOLL io_uring instance to handle
|
||||
asynchronous file system operations.
|
||||
|
||||
.. versionchanged:: 1.39.0 added the UV_METRICS_IDLE_TIME option.
|
||||
|
||||
.. versionchanged:: 1.49.0 added the UV_LOOP_ENABLE_IO_URING_SQPOLL option.
|
||||
|
||||
.. c:function:: int uv_loop_close(uv_loop_t* loop)
|
||||
|
||||
Releases all internal loop resources. Call this function only when the loop
|
||||
@ -238,7 +256,7 @@ API
|
||||
|
||||
.. versionadded:: 1.19.0
|
||||
|
||||
.. c:function:: void* uv_loop_set_data(uv_loop_t* loop, void* data)
|
||||
.. c:function:: void uv_loop_set_data(uv_loop_t* loop, void* data)
|
||||
|
||||
Sets `loop->data` to `data`.
|
||||
|
||||
|
||||
@ -4,8 +4,46 @@
|
||||
Metrics operations
|
||||
======================
|
||||
|
||||
libuv provides a metrics API to track the amount of time the event loop has
|
||||
spent idle in the kernel's event provider.
|
||||
libuv provides a metrics API to track various internal operations of the event
|
||||
loop.
|
||||
|
||||
|
||||
Data types
|
||||
----------
|
||||
|
||||
.. c:type:: uv_metrics_t
|
||||
|
||||
The struct that contains event loop metrics. It is recommended to retrieve
|
||||
these metrics in a :c:type:`uv_prepare_cb` in order to make sure there are
|
||||
no inconsistencies with the metrics counters.
|
||||
|
||||
::
|
||||
|
||||
typedef struct {
|
||||
uint64_t loop_count;
|
||||
uint64_t events;
|
||||
uint64_t events_waiting;
|
||||
/* private */
|
||||
uint64_t* reserved[13];
|
||||
} uv_metrics_t;
|
||||
|
||||
|
||||
Public members
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
.. c:member:: uint64_t uv_metrics_t.loop_count
|
||||
|
||||
Number of event loop iterations.
|
||||
|
||||
.. c:member:: uint64_t uv_metrics_t.events
|
||||
|
||||
Number of events that have been processed by the event handler.
|
||||
|
||||
.. c:member:: uint64_t uv_metrics_t.events_waiting
|
||||
|
||||
Number of events that were waiting to be processed when the event provider
|
||||
was called.
|
||||
|
||||
|
||||
API
|
||||
---
|
||||
@ -25,3 +63,9 @@ API
|
||||
:c:type:`UV_METRICS_IDLE_TIME`.
|
||||
|
||||
.. versionadded:: 1.39.0
|
||||
|
||||
.. c:function:: int uv_metrics_info(uv_loop_t* loop, uv_metrics_t* metrics)
|
||||
|
||||
Copy the current set of event loop metrics to the ``metrics`` pointer.
|
||||
|
||||
.. versionadded:: 1.45.0
|
||||
|
||||
@ -73,7 +73,8 @@ Data types
|
||||
|
||||
.. c:type:: uv_timeval_t
|
||||
|
||||
Data type for storing times.
|
||||
Y2K38-unsafe data type for storing times with microsecond resolution.
|
||||
Will be replaced with :c:type:`uv_timeval64_t` in libuv v2.0.
|
||||
|
||||
::
|
||||
|
||||
@ -84,7 +85,7 @@ Data types
|
||||
|
||||
.. c:type:: uv_timeval64_t
|
||||
|
||||
Alternative data type for storing times.
|
||||
Y2K38-safe data type for storing times with microsecond resolution.
|
||||
|
||||
::
|
||||
|
||||
@ -93,6 +94,28 @@ Data types
|
||||
int32_t tv_usec;
|
||||
} uv_timeval64_t;
|
||||
|
||||
.. c:type:: uv_timespec64_t
|
||||
|
||||
Y2K38-safe data type for storing times with nanosecond resolution.
|
||||
|
||||
::
|
||||
|
||||
typedef struct {
|
||||
int64_t tv_sec;
|
||||
int32_t tv_nsec;
|
||||
} uv_timespec64_t;
|
||||
|
||||
.. c:enum:: uv_clock_id
|
||||
|
||||
Clock source for :c:func:`uv_clock_gettime`.
|
||||
|
||||
::
|
||||
|
||||
typedef enum {
|
||||
UV_CLOCK_MONOTONIC,
|
||||
UV_CLOCK_REALTIME
|
||||
} uv_clock_id;
|
||||
|
||||
.. c:type:: uv_rusage_t
|
||||
|
||||
Data type for resource usage results.
|
||||
@ -119,7 +142,10 @@ Data types
|
||||
} uv_rusage_t;
|
||||
|
||||
Members marked with `(X)` are unsupported on Windows.
|
||||
See :man:`getrusage(2)` for supported fields on Unix
|
||||
See :man:`getrusage(2)` for supported fields on UNIX-like platforms.
|
||||
|
||||
The maximum resident set size is reported in kilobytes, the unit most
|
||||
platforms use natively.
|
||||
|
||||
.. c:type:: uv_cpu_info_t
|
||||
|
||||
@ -173,6 +199,18 @@ Data types
|
||||
char* homedir;
|
||||
} uv_passwd_t;
|
||||
|
||||
.. c:type:: uv_group_t
|
||||
|
||||
Data type for group file information.
|
||||
|
||||
::
|
||||
|
||||
typedef struct uv_group_s {
|
||||
char* groupname;
|
||||
unsigned long gid;
|
||||
char** members;
|
||||
} uv_group_t;
|
||||
|
||||
.. c:type:: uv_utsname_t
|
||||
|
||||
Data type for operating system name and version information.
|
||||
@ -211,7 +249,7 @@ API
|
||||
type of the stdio streams.
|
||||
|
||||
For :man:`isatty(3)` equivalent functionality use this function and test
|
||||
for ``UV_TTY``.
|
||||
for `UV_TTY`.
|
||||
|
||||
.. c:function:: int uv_replace_allocator(uv_malloc_func malloc_func, uv_realloc_func realloc_func, uv_calloc_func calloc_func, uv_free_func free_func)
|
||||
|
||||
@ -225,8 +263,8 @@ API
|
||||
after all resources have been freed and thus libuv doesn't reference
|
||||
any allocated memory chunk.
|
||||
|
||||
On success, it returns 0, if any of the function pointers is NULL it
|
||||
returns UV_EINVAL.
|
||||
On success, it returns 0, if any of the function pointers is `NULL` it
|
||||
returns `UV_EINVAL`.
|
||||
|
||||
.. warning:: There is no protection against changing the allocator multiple
|
||||
times. If the user changes it they are responsible for making
|
||||
@ -312,7 +350,7 @@ API
|
||||
|
||||
.. c:function:: int uv_uptime(double* uptime)
|
||||
|
||||
Gets the current system uptime.
|
||||
Gets the current system uptime. Depending on the system full or fractional seconds are returned.
|
||||
|
||||
.. c:function:: int uv_getrusage(uv_rusage_t* rusage)
|
||||
|
||||
@ -322,6 +360,17 @@ API
|
||||
On Windows not all fields are set, the unsupported fields are filled with zeroes.
|
||||
See :c:type:`uv_rusage_t` for more details.
|
||||
|
||||
.. c:function:: int uv_getrusage_thread(uv_rusage_t* rusage)
|
||||
|
||||
Gets the resource usage measures for the calling thread.
|
||||
|
||||
.. versionadded:: 1.50.0
|
||||
|
||||
.. note::
|
||||
Not supported on all platforms. May return `UV_ENOTSUP`.
|
||||
On macOS and Windows not all fields are set, the unsupported fields are filled with zeroes.
|
||||
See :c:type:`uv_rusage_t` for more details.
|
||||
|
||||
.. c:function:: uv_pid_t uv_os_getpid(void)
|
||||
|
||||
Returns the current process ID.
|
||||
@ -334,15 +383,41 @@ API
|
||||
|
||||
.. versionadded:: 1.16.0
|
||||
|
||||
.. c:function:: unsigned int uv_available_parallelism(void)
|
||||
|
||||
Returns an estimate of the default amount of parallelism a program should
|
||||
use. Always returns a non-zero value.
|
||||
|
||||
On Linux, inspects the calling thread's CPU affinity mask to determine if
|
||||
it has been pinned to specific CPUs.
|
||||
|
||||
On Windows, the available parallelism may be underreported on systems with
|
||||
more than 64 logical CPUs.
|
||||
|
||||
On other platforms, reports the number of CPUs that the operating system
|
||||
considers to be online.
|
||||
|
||||
.. versionadded:: 1.44.0
|
||||
|
||||
.. c:function:: int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count)
|
||||
|
||||
Gets information about the CPUs on the system. The `cpu_infos` array will
|
||||
have `count` elements and needs to be freed with :c:func:`uv_free_cpu_info`.
|
||||
|
||||
Use :c:func:`uv_available_parallelism` if you need to know how many CPUs
|
||||
are available for threads or child processes.
|
||||
|
||||
.. c:function:: void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count)
|
||||
|
||||
Frees the `cpu_infos` array previously allocated with :c:func:`uv_cpu_info`.
|
||||
|
||||
.. c:function:: int uv_cpumask_size(void)
|
||||
|
||||
Returns the maximum size of the mask used for process/thread affinities,
|
||||
or `UV_ENOTSUP` if affinities are not supported on the current platform.
|
||||
|
||||
.. versionadded:: 1.45.0
|
||||
|
||||
.. c:function:: int uv_interface_addresses(uv_interface_address_t** addresses, int* count)
|
||||
|
||||
Gets address information about the network interfaces on the system. An
|
||||
@ -514,6 +589,35 @@ API
|
||||
|
||||
.. versionadded:: 1.9.0
|
||||
|
||||
.. c:function:: int uv_os_get_passwd2(uv_passwd_t* pwd, uv_uid_t uid)
|
||||
|
||||
Gets a subset of the password file entry for the provided uid.
|
||||
The populated data includes the username, euid, gid, shell,
|
||||
and home directory. On non-Windows systems, all data comes from
|
||||
:man:`getpwuid_r(3)`. On Windows, uid and gid are set to -1 and have no
|
||||
meaning, and shell is `NULL`. After successfully calling this function, the
|
||||
memory allocated to `pwd` needs to be freed with
|
||||
:c:func:`uv_os_free_passwd`.
|
||||
|
||||
.. versionadded:: 1.45.0
|
||||
|
||||
.. c:function:: int uv_os_get_group(uv_group_t* group, uv_uid_t gid)
|
||||
|
||||
Gets a subset of the group file entry for the provided uid.
|
||||
The populated data includes the group name, gid, and members. On non-Windows
|
||||
systems, all data comes from :man:`getgrgid_r(3)`. On Windows, uid and gid
|
||||
are set to -1 and have no meaning. After successfully calling this function,
|
||||
the memory allocated to `group` needs to be freed with
|
||||
:c:func:`uv_os_free_group`.
|
||||
|
||||
.. versionadded:: 1.45.0
|
||||
|
||||
.. c:function:: void uv_os_free_group(uv_passwd_t* pwd)
|
||||
|
||||
Frees the memory previously allocated with :c:func:`uv_os_get_group`.
|
||||
|
||||
.. versionadded:: 1.45.0
|
||||
|
||||
.. c:function:: void uv_os_free_passwd(uv_passwd_t* pwd)
|
||||
|
||||
Frees the `pwd` memory previously allocated with :c:func:`uv_os_get_passwd`.
|
||||
@ -522,18 +626,21 @@ API
|
||||
|
||||
.. c:function:: uint64_t uv_get_free_memory(void)
|
||||
|
||||
Gets the amount of free memory available in the system, as reported by the kernel (in bytes).
|
||||
Gets the amount of free memory available in the system, as reported by
|
||||
the kernel (in bytes). Returns 0 when unknown.
|
||||
|
||||
.. c:function:: uint64_t uv_get_total_memory(void)
|
||||
|
||||
Gets the total amount of physical memory in the system (in bytes).
|
||||
Returns 0 when unknown.
|
||||
|
||||
.. c:function:: uint64_t uv_get_constrained_memory(void)
|
||||
|
||||
Gets the amount of memory available to the process (in bytes) based on
|
||||
Gets the total amount of memory available to the process (in bytes) based on
|
||||
limits imposed by the OS. If there is no such constraint, or the constraint
|
||||
is unknown, `0` is returned. Note that it is not unusual for this value to
|
||||
be less than or greater than :c:func:`uv_get_total_memory`.
|
||||
is unknown, `0` is returned. If there is a constraining mechanism, but there
|
||||
is no constraint set, `UINT64_MAX` is returned. Note that it is not unusual
|
||||
for this value to be less than or greater than :c:func:`uv_get_total_memory`.
|
||||
|
||||
.. note::
|
||||
This function currently only returns a non-zero value on Linux, based
|
||||
@ -541,9 +648,23 @@ API
|
||||
|
||||
.. versionadded:: 1.29.0
|
||||
|
||||
.. c:function:: uint64_t uv_get_available_memory(void)
|
||||
|
||||
Gets the amount of free memory that is still available to the process (in bytes).
|
||||
This differs from :c:func:`uv_get_free_memory` in that it takes into account any
|
||||
limits imposed by the OS. If there is no such constraint, or the constraint
|
||||
is unknown, the amount returned will be identical to :c:func:`uv_get_free_memory`.
|
||||
|
||||
.. note::
|
||||
This function currently only returns a value that is different from
|
||||
what :c:func:`uv_get_free_memory` reports on Linux, based
|
||||
on cgroups if it is present.
|
||||
|
||||
.. versionadded:: 1.45.0
|
||||
|
||||
.. c:function:: uint64_t uv_hrtime(void)
|
||||
|
||||
Returns the current high-resolution real time. This is expressed in
|
||||
Returns the current high-resolution timestamp. This is expressed in
|
||||
nanoseconds. It is relative to an arbitrary time in the past. It is not
|
||||
related to the time of day and therefore not subject to clock drift. The
|
||||
primary use is for measuring performance between intervals.
|
||||
@ -552,6 +673,19 @@ API
|
||||
Not every platform can support nanosecond resolution; however, this value will always
|
||||
be in nanoseconds.
|
||||
|
||||
.. c:function:: int uv_clock_gettime(uv_clock_id clock_id, uv_timespec64_t* ts)
|
||||
|
||||
Obtain the current system time from a high-resolution real-time or monotonic
|
||||
clock source.
|
||||
|
||||
The real-time clock counts from the UNIX epoch (1970-01-01) and is subject
|
||||
to time adjustments; it can jump back in time.
|
||||
|
||||
The monotonic clock counts from an arbitrary point in the past and never
|
||||
jumps back in time.
|
||||
|
||||
.. versionadded:: 1.45.0
|
||||
|
||||
.. c:function:: void uv_print_all_handles(uv_loop_t* loop, FILE* stream)
|
||||
|
||||
Prints all handles associated with the given `loop` to the given `stream`.
|
||||
@ -757,3 +891,50 @@ API
|
||||
Causes the calling thread to sleep for `msec` milliseconds.
|
||||
|
||||
.. versionadded:: 1.34.0
|
||||
|
||||
String manipulation functions
|
||||
-----------------------------
|
||||
|
||||
These string utilities are needed internally for dealing with Windows, and are
|
||||
exported to allow clients to work uniformly with this data when the libuv API
|
||||
is not complete.
|
||||
|
||||
.. c:function:: size_t uv_utf16_length_as_wtf8(const uint16_t* utf16, ssize_t utf16_len)
|
||||
|
||||
Get the length of a UTF-16 (or UCS-2) `utf16` value after converting it to
|
||||
WTF-8. If `utf16` is NUL terminated, `utf16_len` can be set to -1,
|
||||
otherwise it must be specified.
|
||||
|
||||
.. versionadded:: 1.47.0
|
||||
|
||||
.. c:function:: int uv_utf16_to_wtf8(const uint16_t* utf16, ssize_t utf16_len, char** wtf8_ptr, size_t* wtf8_len_ptr)
|
||||
|
||||
Convert UTF-16 (or UCS-2) data in `utf16` to WTF-8 data in `*wtf8_ptr`. The
|
||||
`utf16_len` count (in characters) gives the length of `utf16`. If `utf16`
|
||||
is NUL terminated, `utf16_len` can be set to -1, otherwise it must be
|
||||
specified. If `wtf8_ptr` is `NULL`, no result will be computed, but the
|
||||
length (equal to `uv_utf16_length_as_wtf8`) will be stored in `wtf8_ptr`.
|
||||
If `*wtf8_ptr` is `NULL`, space for the conversion will be allocated and
|
||||
returned in `wtf8_ptr` and the length will be returned in `wtf8_len_ptr`.
|
||||
Otherwise, the length of `*wtf8_ptr` must be passed in `wtf8_len_ptr`. The
|
||||
`wtf8_ptr` must contain an extra space for an extra NUL after the result.
|
||||
If the result is truncated, `UV_ENOBUFS` will be returned and
|
||||
`wtf8_len_ptr` will be the length of the required `wtf8_ptr` to contain the
|
||||
whole result.
|
||||
|
||||
.. versionadded:: 1.47.0
|
||||
|
||||
.. c:function:: ssize_t uv_wtf8_length_as_utf16(const char* wtf8)
|
||||
|
||||
Get the length in characters of a NUL-terminated WTF-8 `wtf8` value
|
||||
after converting it to UTF-16 (or UCS-2), including NUL terminator.
|
||||
|
||||
.. versionadded:: 1.47.0
|
||||
|
||||
.. c:function:: void uv_wtf8_to_utf16(const char* utf8, uint16_t* utf16, size_t utf16_len)
|
||||
|
||||
Convert NUL-terminated WTF-8 data in `wtf8` to UTF-16 (or UCS-2) data
|
||||
in `utf16`. The `utf16_len` count (in characters) must include space
|
||||
for the NUL terminator.
|
||||
|
||||
.. versionadded:: 1.47.0
|
||||
|
||||
@ -55,17 +55,61 @@ API
|
||||
|
||||
Bind the pipe to a file path (Unix) or a name (Windows).
|
||||
|
||||
Does not support Linux abstract namespace sockets,
|
||||
unlike :c:func:`uv_pipe_bind2`.
|
||||
|
||||
Alias for ``uv_pipe_bind2(handle, name, strlen(name), 0)``.
|
||||
|
||||
.. note::
|
||||
Paths on Unix get truncated to ``sizeof(sockaddr_un.sun_path)`` bytes, typically between
|
||||
92 and 108 bytes.
|
||||
Paths on Unix get truncated to ``sizeof(sockaddr_un.sun_path)`` bytes,
|
||||
typically between 92 and 108 bytes.
|
||||
|
||||
.. c:function:: int uv_pipe_bind2(uv_pipe_t* handle, const char* name, size_t namelen, unsigned int flags)
|
||||
|
||||
Bind the pipe to a file path (Unix) or a name (Windows).
|
||||
|
||||
``flags`` must be zero or ``UV_PIPE_NO_TRUNCATE``. Returns ``UV_EINVAL``
|
||||
for unsupported flags without performing the bind operation.
|
||||
|
||||
Supports Linux abstract namespace sockets. ``namelen`` must include
|
||||
the leading nul byte but not the trailing nul byte.
|
||||
|
||||
.. versionadded:: 1.46.0
|
||||
|
||||
.. note::
|
||||
Paths on Unix get truncated to ``sizeof(sockaddr_un.sun_path)`` bytes,
|
||||
typically between 92 and 108 bytes, unless the ``UV_PIPE_NO_TRUNCATE``
|
||||
flag is specified, in which case an ``UV_EINVAL`` error is returned.
|
||||
|
||||
.. c:function:: void uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle, const char* name, uv_connect_cb cb)
|
||||
|
||||
Connect to the Unix domain socket or the named pipe.
|
||||
Connect to the Unix domain socket or the Windows named pipe.
|
||||
|
||||
Does not support Linux abstract namespace sockets,
|
||||
unlike :c:func:`uv_pipe_connect2`.
|
||||
|
||||
Alias for ``uv_pipe_connect2(req, handle, name, strlen(name), 0, cb)``.
|
||||
|
||||
.. note::
|
||||
Paths on Unix get truncated to ``sizeof(sockaddr_un.sun_path)`` bytes, typically between
|
||||
92 and 108 bytes.
|
||||
Paths on Unix get truncated to ``sizeof(sockaddr_un.sun_path)`` bytes,
|
||||
typically between 92 and 108 bytes.
|
||||
|
||||
.. c:function:: void uv_pipe_connect2(uv_connect_t* req, uv_pipe_t* handle, const char* name, size_t namelen, unsigned int flags, uv_connect_cb cb)
|
||||
|
||||
Connect to the Unix domain socket or the Windows named pipe.
|
||||
|
||||
``flags`` must be zero or ``UV_PIPE_NO_TRUNCATE``. Returns ``UV_EINVAL``
|
||||
for unsupported flags without performing the connect operation.
|
||||
|
||||
Supports Linux abstract namespace sockets. ``namelen`` must include
|
||||
the leading nul byte but not the trailing nul byte.
|
||||
|
||||
.. versionadded:: 1.46.0
|
||||
|
||||
.. note::
|
||||
Paths on Unix get truncated to ``sizeof(sockaddr_un.sun_path)`` bytes,
|
||||
typically between 92 and 108 bytes, unless the ``UV_PIPE_NO_TRUNCATE``
|
||||
flag is specified, in which case an ``UV_EINVAL`` error is returned.
|
||||
|
||||
.. c:function:: int uv_pipe_getsockname(const uv_pipe_t* handle, char* buffer, size_t* size)
|
||||
|
||||
|
||||
@ -45,7 +45,7 @@ Data types
|
||||
|
||||
Type definition for callback passed to :c:func:`uv_poll_start`.
|
||||
|
||||
.. c:type:: uv_poll_event
|
||||
.. c:enum:: uv_poll_event
|
||||
|
||||
Poll event types
|
||||
|
||||
@ -101,7 +101,9 @@ API
|
||||
with one of the `UV_E*` error codes (see :ref:`errors`). The user should
|
||||
not close the socket while the handle is active. If the user does that
|
||||
anyway, the callback *may* be called reporting an error status, but this is
|
||||
**not** guaranteed.
|
||||
**not** guaranteed. If `status == UV_EBADF` polling is discontinued for the
|
||||
file handle and no further events will be reported. The user should
|
||||
then call :c:func:`uv_close` on the handle.
|
||||
|
||||
.. note::
|
||||
Calling :c:func:`uv_poll_start` on a handle that is already active is
|
||||
|
||||
@ -40,7 +40,7 @@ Data types
|
||||
will indicate the exit status and the signal that caused the process to
|
||||
terminate, if any.
|
||||
|
||||
.. c:type:: uv_process_flags
|
||||
.. c:enum:: uv_process_flags
|
||||
|
||||
Flags to be set on the flags field of :c:type:`uv_process_options_t`.
|
||||
|
||||
@ -85,7 +85,14 @@ Data types
|
||||
* option is only meaningful on Windows systems. On Unix it is silently
|
||||
* ignored.
|
||||
*/
|
||||
UV_PROCESS_WINDOWS_HIDE_GUI = (1 << 6)
|
||||
UV_PROCESS_WINDOWS_HIDE_GUI = (1 << 6),
|
||||
/*
|
||||
* On Windows, if the path to the program to execute, specified in
|
||||
* uv_process_options_t's file field, has a directory component,
|
||||
* search for the exact file name before trying variants with
|
||||
* extensions like '.exe' or '.cmd'.
|
||||
*/
|
||||
UV_PROCESS_WINDOWS_FILE_PATH_EXACT_NAME = (1 << 7)
|
||||
};
|
||||
|
||||
.. c:type:: uv_stdio_container_t
|
||||
@ -109,10 +116,39 @@ Data types
|
||||
::
|
||||
|
||||
typedef enum {
|
||||
/*
|
||||
* The following four options are mutually-exclusive, and define
|
||||
* the operation to perform for the corresponding file descriptor
|
||||
* in the child process:
|
||||
*/
|
||||
|
||||
/*
|
||||
* No file descriptor will be provided (or redirected to
|
||||
* `/dev/null` if it is fd 0, 1 or 2).
|
||||
*/
|
||||
UV_IGNORE = 0x00,
|
||||
|
||||
/*
|
||||
* Open a new pipe into `data.stream`, per the flags below. The
|
||||
* `data.stream` field must point to a uv_pipe_t object that has
|
||||
* been initialized with `uv_pipe_init(loop, data.stream, ipc);`,
|
||||
* but not yet opened or connected.
|
||||
/*
|
||||
UV_CREATE_PIPE = 0x01,
|
||||
|
||||
/*
|
||||
* The child process will be given a duplicate of the parent's
|
||||
* file descriptor given by `data.fd`.
|
||||
*/
|
||||
UV_INHERIT_FD = 0x02,
|
||||
|
||||
/*
|
||||
* The child process will be given a duplicate of the parent's
|
||||
* file descriptor being used by the stream handle given by
|
||||
* `data.stream`.
|
||||
*/
|
||||
UV_INHERIT_STREAM = 0x04,
|
||||
|
||||
/*
|
||||
* When UV_CREATE_PIPE is specified, UV_READABLE_PIPE and UV_WRITABLE_PIPE
|
||||
* determine the direction of flow, from the child process' perspective. Both
|
||||
@ -120,6 +156,7 @@ Data types
|
||||
*/
|
||||
UV_READABLE_PIPE = 0x10,
|
||||
UV_WRITABLE_PIPE = 0x20,
|
||||
|
||||
/*
|
||||
* When UV_CREATE_PIPE is specified, specifying UV_NONBLOCK_PIPE opens the
|
||||
* handle in non-blocking mode in the child. This may cause loss of data,
|
||||
@ -153,7 +190,7 @@ Public members
|
||||
Command line arguments. args[0] should be the path to the program. On
|
||||
Windows this uses `CreateProcess` which concatenates the arguments into a
|
||||
string this can cause some strange errors. See the
|
||||
``UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS`` flag on :c:type:`uv_process_flags`.
|
||||
``UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS`` flag on :c:enum:`uv_process_flags`.
|
||||
|
||||
.. c:member:: char** uv_process_options_t.env
|
||||
|
||||
@ -166,7 +203,7 @@ Public members
|
||||
.. c:member:: unsigned int uv_process_options_t.flags
|
||||
|
||||
Various flags that control how :c:func:`uv_spawn` behaves. See
|
||||
:c:type:`uv_process_flags`.
|
||||
:c:enum:`uv_process_flags`.
|
||||
|
||||
.. c:member:: int uv_process_options_t.stdio_count
|
||||
.. c:member:: uv_stdio_container_t* uv_process_options_t.stdio
|
||||
@ -232,6 +269,9 @@ API
|
||||
.. versionchanged:: 1.24.0 Added `UV_PROCESS_WINDOWS_HIDE_CONSOLE` and
|
||||
`UV_PROCESS_WINDOWS_HIDE_GUI` flags.
|
||||
|
||||
.. versionchanged:: 1.48.0 Added the
|
||||
`UV_PROCESS_WINDOWS_FILE_PATH_EXACT_NAME` flag.
|
||||
|
||||
.. c:function:: int uv_process_kill(uv_process_t* handle, int signum)
|
||||
|
||||
Sends the specified signal to the given process handle. Check the documentation
|
||||
|
||||
@ -21,17 +21,9 @@ Data types
|
||||
|
||||
Union of all request types.
|
||||
|
||||
.. c:enum:: uv_req_type
|
||||
|
||||
Public members
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
.. c:member:: void* uv_req_t.data
|
||||
|
||||
Space for user-defined arbitrary data. libuv does not use this field.
|
||||
|
||||
.. c:member:: uv_req_type uv_req_t.type
|
||||
|
||||
Indicated the type of request. Readonly.
|
||||
The kind of the libuv request.
|
||||
|
||||
::
|
||||
|
||||
@ -50,6 +42,18 @@ Public members
|
||||
} uv_req_type;
|
||||
|
||||
|
||||
Public members
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
.. c:member:: void* uv_req_t.data
|
||||
|
||||
Space for user-defined arbitrary data. libuv does not use this field.
|
||||
|
||||
.. c:member:: uv_req_type uv_req_t.type
|
||||
|
||||
The :c:enum:`uv_req_type`, indicating the type of the request. Readonly.
|
||||
|
||||
|
||||
API
|
||||
---
|
||||
|
||||
@ -95,7 +99,7 @@ API
|
||||
|
||||
.. versionadded:: 1.19.0
|
||||
|
||||
.. c:function:: void* uv_req_set_data(uv_req_t* req, void* data)
|
||||
.. c:function:: void uv_req_set_data(uv_req_t* req, void* data)
|
||||
|
||||
Sets `req->data` to `data`.
|
||||
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 79 KiB After Width: | Height: | Size: 64 KiB |
@ -16,6 +16,28 @@ Data types
|
||||
|
||||
TCP handle type.
|
||||
|
||||
.. c:enum:: uv_tcp_flags
|
||||
|
||||
Flags used in :c:func:`uv_tcp_bind`.
|
||||
|
||||
::
|
||||
|
||||
enum uv_tcp_flags {
|
||||
/* Used with uv_tcp_bind, when an IPv6 address is used. */
|
||||
UV_TCP_IPV6ONLY = 1,
|
||||
|
||||
/* Enable SO_REUSEPORT socket option when binding the handle.
|
||||
* This allows completely duplicate bindings by multiple processes
|
||||
* or threads if they all set SO_REUSEPORT before binding the port.
|
||||
* Incoming connections are distributed across the participating
|
||||
* listener sockets.
|
||||
*
|
||||
* This flag is available only on Linux 3.9+, DragonFlyBSD 3.6+,
|
||||
* FreeBSD 12.0+, Solaris 11.4, and AIX 7.2.5+ for now.
|
||||
*/
|
||||
UV_TCP_REUSEPORT = 2,
|
||||
};
|
||||
|
||||
|
||||
Public members
|
||||
^^^^^^^^^^^^^^
|
||||
@ -65,6 +87,10 @@ API
|
||||
at the end of this procedure, then the handle is destroyed with a
|
||||
``UV_ETIMEDOUT`` error passed to the corresponding callback.
|
||||
|
||||
If `delay` is less than 1 then ``UV_EINVAL`` is returned.
|
||||
|
||||
.. versionchanged:: 1.49.0 If `delay` is less than 1 then ``UV_EINVAL``` is returned.
|
||||
|
||||
.. c:function:: int uv_tcp_simultaneous_accepts(uv_tcp_t* handle, int enable)
|
||||
|
||||
Enable / disable simultaneous asynchronous accept requests that are
|
||||
@ -77,16 +103,34 @@ API
|
||||
|
||||
.. c:function:: int uv_tcp_bind(uv_tcp_t* handle, const struct sockaddr* addr, unsigned int flags)
|
||||
|
||||
Bind the handle to an address and port. `addr` should point to an
|
||||
initialized ``struct sockaddr_in`` or ``struct sockaddr_in6``.
|
||||
Bind the handle to an address and port.
|
||||
|
||||
When the port is already taken, you can expect to see an ``UV_EADDRINUSE``
|
||||
error from :c:func:`uv_listen` or :c:func:`uv_tcp_connect`. That is,
|
||||
a successful call to this function does not guarantee that the call
|
||||
to :c:func:`uv_listen` or :c:func:`uv_tcp_connect` will succeed as well.
|
||||
error from :c:func:`uv_listen` or :c:func:`uv_tcp_connect` unless you specify
|
||||
``UV_TCP_REUSEPORT`` in `flags` for all the binding sockets. That is, a successful
|
||||
call to this function does not guarantee that the call to :c:func:`uv_listen` or
|
||||
:c:func:`uv_tcp_connect` will succeed as well.
|
||||
|
||||
`flags` can contain ``UV_TCP_IPV6ONLY``, in which case dual-stack support
|
||||
is disabled and only IPv6 is used.
|
||||
:param handle: TCP handle. It should have been initialized with :c:func:`uv_tcp_init`.
|
||||
|
||||
:param addr: Address to bind to. It should point to an initialized ``struct sockaddr_in``
|
||||
or ``struct sockaddr_in6``.
|
||||
|
||||
:param flags: Flags that control the behavior of binding the socket.
|
||||
``UV_TCP_IPV6ONLY`` can be contained in `flags` to disable dual-stack
|
||||
support and only use IPv6.
|
||||
``UV_TCP_REUSEPORT`` can be contained in `flags` to enable the socket option
|
||||
`SO_REUSEPORT` with the capability of load balancing that distribute incoming
|
||||
connections across all listening sockets in multiple processes or threads.
|
||||
|
||||
:returns: 0 on success, or an error code < 0 on failure.
|
||||
|
||||
.. versionchanged:: 1.49.0 added the ``UV_TCP_REUSEPORT`` flag.
|
||||
|
||||
.. note::
|
||||
``UV_TCP_REUSEPORT`` flag is available only on Linux 3.9+, DragonFlyBSD 3.6+,
|
||||
FreeBSD 12.0+, Solaris 11.4, and AIX 7.2.5+ at the moment. On other platforms
|
||||
this function will return an UV_ENOTSUP error.
|
||||
|
||||
.. c:function:: int uv_tcp_getsockname(const uv_tcp_t* handle, struct sockaddr* name, int* namelen)
|
||||
|
||||
|
||||
@ -78,6 +78,14 @@ Threads
|
||||
|
||||
.. versionchanged:: 1.4.1 returns a UV_E* error code on failure
|
||||
|
||||
.. c:function:: int uv_thread_detach(uv_thread_t* tid)
|
||||
|
||||
Detaches a thread. Detached threads automatically release their
|
||||
resources upon termination, eliminating the need for the application to
|
||||
call `uv_thread_join`.
|
||||
|
||||
.. versionadded:: 1.50.0
|
||||
|
||||
.. c:function:: int uv_thread_create_ex(uv_thread_t* tid, const uv_thread_options_t* params, uv_thread_cb entry, void* arg)
|
||||
|
||||
Like :c:func:`uv_thread_create`, but additionally specifies options for creating a new thread.
|
||||
@ -88,10 +96,89 @@ Threads
|
||||
|
||||
.. versionadded:: 1.26.0
|
||||
|
||||
.. c:function:: int uv_thread_setaffinity(uv_thread_t* tid, char* cpumask, char* oldmask, size_t mask_size)
|
||||
|
||||
Sets the specified thread's affinity to cpumask, which is specified in
|
||||
bytes. Optionally returning the previous affinity setting in oldmask.
|
||||
On Unix, uses :man:`pthread_getaffinity_np(3)` to get the affinity setting
|
||||
and maps the cpu_set_t to bytes in oldmask. Then maps the bytes in cpumask
|
||||
to a cpu_set_t and uses :man:`pthread_setaffinity_np(3)`. On Windows, maps
|
||||
the bytes in cpumask to a bitmask and uses SetThreadAffinityMask() which
|
||||
returns the previous affinity setting.
|
||||
|
||||
The mask_size specifies the number of entries (bytes) in cpumask / oldmask,
|
||||
and must be greater-than-or-equal-to :c:func:`uv_cpumask_size`.
|
||||
|
||||
.. note::
|
||||
Thread affinity setting is not atomic on Windows. Unsupported on macOS.
|
||||
|
||||
.. versionadded:: 1.45.0
|
||||
|
||||
.. c:function:: int uv_thread_getaffinity(uv_thread_t* tid, char* cpumask, size_t mask_size)
|
||||
|
||||
Gets the specified thread's affinity setting. On Unix, this maps the
|
||||
cpu_set_t returned by :man:`pthread_getaffinity_np(3)` to bytes in cpumask.
|
||||
|
||||
The mask_size specifies the number of entries (bytes) in cpumask,
|
||||
and must be greater-than-or-equal-to :c:func:`uv_cpumask_size`.
|
||||
|
||||
.. note::
|
||||
Thread affinity getting is not atomic on Windows. Unsupported on macOS.
|
||||
|
||||
.. versionadded:: 1.45.0
|
||||
|
||||
.. c:function:: int uv_thread_getcpu(void)
|
||||
|
||||
Gets the CPU number on which the calling thread is running.
|
||||
|
||||
.. note::
|
||||
Currently only implemented on Windows, Linux and FreeBSD.
|
||||
|
||||
.. versionadded:: 1.45.0
|
||||
|
||||
.. c:function:: uv_thread_t uv_thread_self(void)
|
||||
.. c:function:: int uv_thread_join(uv_thread_t *tid)
|
||||
.. c:function:: int uv_thread_equal(const uv_thread_t* t1, const uv_thread_t* t2)
|
||||
|
||||
.. c:function:: int uv_thread_setname(const char* name)
|
||||
|
||||
Sets the name of the current thread. Different platforms define different limits on the max number of characters
|
||||
a thread name can be: Linux, IBM i (16), macOS (64), Windows (32767), and NetBSD (32), etc. `uv_thread_setname()`
|
||||
will truncate it in case `name` is larger than the limit of the platform.
|
||||
|
||||
Not supported on Windows Server 2016, returns `UV_ENOSYS`.
|
||||
|
||||
.. versionadded:: 1.50.0
|
||||
|
||||
.. c:function:: int uv_thread_getname(uv_thread_t* tid, char* name, size_t* size)
|
||||
|
||||
Gets the name of the thread specified by `tid`. The thread name is copied, with the trailing NUL, into the buffer
|
||||
pointed to by `name`. The `size` parameter specifies the size of the buffer pointed to by `name`.
|
||||
The buffer should be large enough to hold the name of the thread plus the trailing NUL, or it will be truncated to fit
|
||||
with the trailing NUL.
|
||||
|
||||
Not supported on Windows Server 2016, returns `UV_ENOSYS`.
|
||||
|
||||
.. versionadded:: 1.50.0
|
||||
|
||||
.. c:function:: int uv_thread_setpriority(uv_thread_t tid, int priority)
|
||||
|
||||
If the function succeeds, the return value is 0.
|
||||
If the function fails, the return value is less than zero.
|
||||
Sets the scheduling priority of the thread specified by tid. It requires elevated
|
||||
privilege to set specific priorities on some platforms.
|
||||
The priority can be set to the following constants. UV_THREAD_PRIORITY_HIGHEST,
|
||||
UV_THREAD_PRIORITY_ABOVE_NORMAL, UV_THREAD_PRIORITY_NORMAL,
|
||||
UV_THREAD_PRIORITY_BELOW_NORMAL, UV_THREAD_PRIORITY_LOWEST.
|
||||
|
||||
.. c:function:: int uv_thread_getpriority(uv_thread_t tid, int* priority)
|
||||
|
||||
If the function succeeds, the return value is 0.
|
||||
If the function fails, the return value is less than zero.
|
||||
Retrieves the scheduling priority of the thread specified by tid. The value in the
|
||||
output parameter priority is platform dependent.
|
||||
For Linux, when schedule policy is SCHED_OTHER (default), priority is 0.
|
||||
|
||||
Thread-local storage
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
||||
@ -14,6 +14,11 @@ is 1024).
|
||||
|
||||
.. versionchanged:: 1.30.0 the maximum UV_THREADPOOL_SIZE allowed was increased from 128 to 1024.
|
||||
|
||||
.. versionchanged:: 1.45.0 threads now have an 8 MB stack instead of the
|
||||
(sometimes too low) platform default.
|
||||
|
||||
.. versionchanged:: 1.50.0 threads now have a default name of libuv-worker.
|
||||
|
||||
The threadpool is global and shared across all event loops. When a particular
|
||||
function makes use of the threadpool (i.e. when using :c:func:`uv_queue_work`)
|
||||
libuv preallocates and initializes the maximum number of threads allowed by
|
||||
|
||||
@ -6,6 +6,15 @@
|
||||
|
||||
Timer handles are used to schedule callbacks to be called in the future.
|
||||
|
||||
Timers are either single-shot or repeating. Repeating timers do not adjust
|
||||
for overhead but are rearmed relative to the event loop's idea of "now".
|
||||
|
||||
Libuv updates its idea of "now" right before executing timer callbacks, and
|
||||
right after waking up from waiting for I/O. See also :c:func:`uv_update_time`.
|
||||
|
||||
Example: a repeating timer with a 50 ms interval whose callback takes 17 ms
|
||||
to complete, runs again 33 ms later. If other tasks take longer than 33 ms,
|
||||
the timer callback runs as soon as possible.
|
||||
|
||||
Data types
|
||||
----------
|
||||
@ -64,11 +73,6 @@ API
|
||||
duration, and will follow normal timer semantics in the case of a
|
||||
time-slice overrun.
|
||||
|
||||
For example, if a 50ms repeating timer first runs for 17ms, it will be
|
||||
scheduled to run again 33ms later. If other tasks consume more than the
|
||||
33ms following the first timer callback, then the callback will run as soon
|
||||
as possible.
|
||||
|
||||
.. note::
|
||||
If the repeat value is set from a timer callback it does not immediately take effect.
|
||||
If the timer was non-repeating before, it will have been stopped. If it was repeating,
|
||||
|
||||
@ -27,10 +27,15 @@ Data types
|
||||
typedef enum {
|
||||
/* Initial/normal terminal mode */
|
||||
UV_TTY_MODE_NORMAL,
|
||||
/* Raw input mode (On Windows, ENABLE_WINDOW_INPUT is also enabled) */
|
||||
/*
|
||||
* Raw input mode (On Windows, ENABLE_WINDOW_INPUT is also enabled).
|
||||
* May become equivalent to UV_TTY_MODE_RAW_VT in future libuv versions.
|
||||
*/
|
||||
UV_TTY_MODE_RAW,
|
||||
/* Binary-safe I/O mode for IPC (Unix-only) */
|
||||
UV_TTY_MODE_IO
|
||||
UV_TTY_MODE_IO,
|
||||
/* Raw input mode. On Windows ENABLE_VIRTUAL_TERMINAL_INPUT is also set. */
|
||||
UV_TTY_MODE_RAW_VT
|
||||
} uv_tty_mode_t;
|
||||
|
||||
.. c:enum:: uv_tty_vtermstate_t
|
||||
@ -98,7 +103,7 @@ API
|
||||
.. c:function:: int uv_tty_set_mode(uv_tty_t* handle, uv_tty_mode_t mode)
|
||||
|
||||
.. versionchanged:: 1.2.0: the mode is specified as a
|
||||
:c:type:`uv_tty_mode_t` value.
|
||||
:c:enum:`uv_tty_mode_t` value.
|
||||
|
||||
Set the TTY using the specified terminal mode.
|
||||
|
||||
|
||||
@ -18,7 +18,7 @@ Data types
|
||||
|
||||
UDP send request type.
|
||||
|
||||
.. c:type:: uv_udp_flags
|
||||
.. c:enum:: uv_udp_flags
|
||||
|
||||
Flags used in :c:func:`uv_udp_bind` and :c:type:`uv_udp_recv_cb`..
|
||||
|
||||
@ -33,12 +33,14 @@ Data types
|
||||
*/
|
||||
UV_UDP_PARTIAL = 2,
|
||||
/*
|
||||
* Indicates if SO_REUSEADDR will be set when binding the handle in
|
||||
* uv_udp_bind.
|
||||
* This sets the SO_REUSEPORT socket flag on the BSDs and OS X. On other
|
||||
* Unix platforms, it sets the SO_REUSEADDR flag. What that means is that
|
||||
* multiple threads or processes can bind to the same address without error
|
||||
* (provided they all set the flag) but only the last one to bind will receive
|
||||
* Indicates if SO_REUSEADDR will be set when binding the handle.
|
||||
* This sets the SO_REUSEPORT socket flag on the BSDs (except for
|
||||
* DragonFlyBSD), OS X, and other platforms where SO_REUSEPORTs don't
|
||||
* have the capability of load balancing, as the opposite of what
|
||||
* UV_UDP_REUSEPORT would do. On other Unix platforms, it sets the
|
||||
* SO_REUSEADDR flag. What that means is that multiple threads or
|
||||
* processes can bind to the same address without error (provided
|
||||
* they all set the flag) but only the last one to bind will receive
|
||||
* any traffic, in effect "stealing" the port from the previous listener.
|
||||
*/
|
||||
UV_UDP_REUSEADDR = 4,
|
||||
@ -56,11 +58,23 @@ Data types
|
||||
/*
|
||||
* Indicates if IP_RECVERR/IPV6_RECVERR will be set when binding the handle.
|
||||
* This sets IP_RECVERR for IPv4 and IPV6_RECVERR for IPv6 UDP sockets on
|
||||
* Linux. This stops the Linux kernel from supressing some ICMP error messages
|
||||
* Linux. This stops the Linux kernel from suppressing some ICMP error messages
|
||||
* and enables full ICMP error reporting for faster failover.
|
||||
* This flag is no-op on platforms other than Linux.
|
||||
*/
|
||||
UV_UDP_LINUX_RECVERR = 32,
|
||||
/*
|
||||
* Indicates if SO_REUSEPORT will be set when binding the handle.
|
||||
* This sets the SO_REUSEPORT socket option on supported platforms.
|
||||
* Unlike UV_UDP_REUSEADDR, this flag will make multiple threads or
|
||||
* processes that are binding to the same address and port "share"
|
||||
* the port, which means incoming datagrams are distributed across
|
||||
* the receiving sockets among threads or processes.
|
||||
*
|
||||
* This flag is available only on Linux 3.9+, DragonFlyBSD 3.6+,
|
||||
* FreeBSD 12.0+, Solaris 11.4, and AIX 7.2.5+ for now.
|
||||
*/
|
||||
UV_UDP_REUSEPORT = 64,
|
||||
/*
|
||||
* Indicates that recvmmsg should be used, if available.
|
||||
*/
|
||||
@ -186,11 +200,24 @@ API
|
||||
with the address and port to bind to.
|
||||
|
||||
:param flags: Indicate how the socket will be bound,
|
||||
``UV_UDP_IPV6ONLY``, ``UV_UDP_REUSEADDR``, and ``UV_UDP_RECVERR``
|
||||
are supported.
|
||||
``UV_UDP_IPV6ONLY``, ``UV_UDP_REUSEADDR``, ``UV_UDP_REUSEPORT``,
|
||||
and ``UV_UDP_RECVERR`` are supported.
|
||||
|
||||
:returns: 0 on success, or an error code < 0 on failure.
|
||||
|
||||
.. versionchanged:: 1.49.0 added the ``UV_UDP_REUSEPORT`` flag.
|
||||
|
||||
.. note::
|
||||
``UV_UDP_REUSEPORT`` flag is available only on Linux 3.9+, DragonFlyBSD 3.6+,
|
||||
FreeBSD 12.0+, Solaris 11.4, and AIX 7.2.5+ at the moment. On other platforms
|
||||
this function will return an UV_ENOTSUP error.
|
||||
For platforms where `SO_REUSEPORT`s have the capability of load balancing,
|
||||
specifying both ``UV_UDP_REUSEADDR`` and ``UV_UDP_REUSEPORT`` in flags is allowed
|
||||
and `SO_REUSEPORT` will always override the behavior of `SO_REUSEADDR`.
|
||||
For platforms where `SO_REUSEPORT`s don't have the capability of load balancing,
|
||||
specifying both ``UV_UDP_REUSEADDR`` and ``UV_UDP_REUSEPORT`` in flags will fail,
|
||||
returning an UV_ENOTSUP error.
|
||||
|
||||
.. c:function:: int uv_udp_connect(uv_udp_t* handle, const struct sockaddr* addr)
|
||||
|
||||
Associate the UDP handle to a remote address and port, so every
|
||||
@ -285,7 +312,9 @@ API
|
||||
local sockets.
|
||||
|
||||
:param handle: UDP handle. Should have been initialized with
|
||||
:c:func:`uv_udp_init`.
|
||||
:c:func:`uv_udp_init_ex` as either ``AF_INET`` or ``AF_INET6``, or have
|
||||
been bound to an address explicitly with :c:func:`uv_udp_bind`, or
|
||||
implicitly with :c:func:`uv_udp_send()` or :c:func:`uv_udp_recv_start`.
|
||||
|
||||
:param on: 1 for on, 0 for off.
|
||||
|
||||
@ -296,7 +325,9 @@ API
|
||||
Set the multicast ttl.
|
||||
|
||||
:param handle: UDP handle. Should have been initialized with
|
||||
:c:func:`uv_udp_init`.
|
||||
:c:func:`uv_udp_init_ex` as either ``AF_INET`` or ``AF_INET6``, or have
|
||||
been bound to an address explicitly with :c:func:`uv_udp_bind`, or
|
||||
implicitly with :c:func:`uv_udp_send()` or :c:func:`uv_udp_recv_start`.
|
||||
|
||||
:param ttl: 1 through 255.
|
||||
|
||||
@ -307,7 +338,9 @@ API
|
||||
Set the multicast interface to send or receive data on.
|
||||
|
||||
:param handle: UDP handle. Should have been initialized with
|
||||
:c:func:`uv_udp_init`.
|
||||
:c:func:`uv_udp_init_ex` as either ``AF_INET`` or ``AF_INET6``, or have
|
||||
been bound to an address explicitly with :c:func:`uv_udp_bind`, or
|
||||
implicitly with :c:func:`uv_udp_send()` or :c:func:`uv_udp_recv_start`.
|
||||
|
||||
:param interface_addr: interface address.
|
||||
|
||||
@ -318,7 +351,9 @@ API
|
||||
Set broadcast on or off.
|
||||
|
||||
:param handle: UDP handle. Should have been initialized with
|
||||
:c:func:`uv_udp_init`.
|
||||
:c:func:`uv_udp_init_ex` as either ``AF_INET`` or ``AF_INET6``, or have
|
||||
been bound to an address explicitly with :c:func:`uv_udp_bind`, or
|
||||
implicitly with :c:func:`uv_udp_send()` or :c:func:`uv_udp_recv_start`.
|
||||
|
||||
:param on: 1 for on, 0 for off.
|
||||
|
||||
@ -329,7 +364,9 @@ API
|
||||
Set the time to live.
|
||||
|
||||
:param handle: UDP handle. Should have been initialized with
|
||||
:c:func:`uv_udp_init`.
|
||||
:c:func:`uv_udp_init_ex` as either ``AF_INET`` or ``AF_INET6``, or have
|
||||
been bound to an address explicitly with :c:func:`uv_udp_bind`, or
|
||||
implicitly with :c:func:`uv_udp_send()` or :c:func:`uv_udp_recv_start`.
|
||||
|
||||
:param ttl: 1 through 255.
|
||||
|
||||
@ -389,6 +426,20 @@ API
|
||||
|
||||
.. versionchanged:: 1.27.0 added support for connected sockets
|
||||
|
||||
.. c:function:: int uv_udp_try_send2(uv_udp_t* handle, unsigned int count, uv_buf_t* bufs[/*count*/], unsigned int nbufs[/*count*/], struct sockaddr* addrs[/*count*/], unsigned int flags)
|
||||
|
||||
Like :c:func:`uv_udp_try_send`, but can send multiple datagrams.
|
||||
Lightweight abstraction around :man:`sendmmsg(2)`, with a :man:`sendmsg(2)`
|
||||
fallback loop for platforms that do not support the former. The handle must
|
||||
be fully initialized; call c:func:`uv_udp_bind` first.
|
||||
|
||||
:returns: >= 0: number of datagrams sent. Zero only if `count` was zero.
|
||||
< 0: negative error code. Only if sending the first datagram fails,
|
||||
otherwise returns a positive send count. ``UV_EAGAIN`` when datagrams
|
||||
cannot be sent right now; fall back to :c:func:`uv_udp_send`.
|
||||
|
||||
.. versionadded:: 1.50.0
|
||||
|
||||
.. c:function:: int uv_udp_recv_start(uv_udp_t* handle, uv_alloc_cb alloc_cb, uv_udp_recv_cb recv_cb)
|
||||
|
||||
Prepare for receiving data. If the socket has not previously been bound
|
||||
|
||||
201
include/uv.h
201
include/uv.h
@ -31,6 +31,7 @@ extern "C" {
|
||||
#error "Define either BUILDING_UV_SHARED or USING_UV_SHARED, not both."
|
||||
#endif
|
||||
|
||||
#ifndef UV_EXTERN
|
||||
#ifdef _WIN32
|
||||
/* Windows - set up dll import/export decorators. */
|
||||
# if defined(BUILDING_UV_SHARED)
|
||||
@ -50,17 +51,20 @@ extern "C" {
|
||||
#else
|
||||
# define UV_EXTERN /* nothing */
|
||||
#endif
|
||||
#endif /* UV_EXTERN */
|
||||
|
||||
#include "uv/errno.h"
|
||||
#include "uv/version.h"
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1600
|
||||
# include "uv/stdint-msvc2008.h"
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
#include <math.h>
|
||||
|
||||
/* Internal type, do not use. */
|
||||
struct uv__queue {
|
||||
struct uv__queue* next;
|
||||
struct uv__queue* prev;
|
||||
};
|
||||
|
||||
#if defined(_WIN32)
|
||||
# include "uv/win.h"
|
||||
@ -152,6 +156,9 @@ extern "C" {
|
||||
XX(EFTYPE, "inappropriate file type or format") \
|
||||
XX(EILSEQ, "illegal byte sequence") \
|
||||
XX(ESOCKTNOSUPPORT, "socket type not supported") \
|
||||
XX(ENODATA, "no data available") \
|
||||
XX(EUNATCH, "protocol driver not attached") \
|
||||
XX(ENOEXEC, "exec format error") \
|
||||
|
||||
#define UV_HANDLE_TYPE_MAP(XX) \
|
||||
XX(ASYNC, async) \
|
||||
@ -247,12 +254,17 @@ typedef struct uv_cpu_info_s uv_cpu_info_t;
|
||||
typedef struct uv_interface_address_s uv_interface_address_t;
|
||||
typedef struct uv_dirent_s uv_dirent_t;
|
||||
typedef struct uv_passwd_s uv_passwd_t;
|
||||
typedef struct uv_group_s uv_group_t;
|
||||
typedef struct uv_utsname_s uv_utsname_t;
|
||||
typedef struct uv_statfs_s uv_statfs_t;
|
||||
|
||||
typedef struct uv_metrics_s uv_metrics_t;
|
||||
|
||||
typedef enum {
|
||||
UV_LOOP_BLOCK_SIGNAL = 0,
|
||||
UV_METRICS_IDLE_TIME
|
||||
UV_METRICS_IDLE_TIME,
|
||||
UV_LOOP_USE_IO_URING_SQPOLL
|
||||
#define UV_LOOP_USE_IO_URING_SQPOLL UV_LOOP_USE_IO_URING_SQPOLL
|
||||
} uv_loop_option;
|
||||
|
||||
typedef enum {
|
||||
@ -282,13 +294,13 @@ UV_EXTERN int uv_loop_init(uv_loop_t* loop);
|
||||
UV_EXTERN int uv_loop_close(uv_loop_t* loop);
|
||||
/*
|
||||
* NOTE:
|
||||
* This function is DEPRECATED (to be removed after 0.12), users should
|
||||
* This function is DEPRECATED, users should
|
||||
* allocate the loop manually and use uv_loop_init instead.
|
||||
*/
|
||||
UV_EXTERN uv_loop_t* uv_loop_new(void);
|
||||
/*
|
||||
* NOTE:
|
||||
* This function is DEPRECATED (to be removed after 0.12). Users should use
|
||||
* This function is DEPRECATED. Users should use
|
||||
* uv_loop_close and free the memory manually instead.
|
||||
*/
|
||||
UV_EXTERN void uv_loop_delete(uv_loop_t*);
|
||||
@ -344,11 +356,32 @@ typedef void (*uv_random_cb)(uv_random_t* req,
|
||||
void* buf,
|
||||
size_t buflen);
|
||||
|
||||
typedef enum {
|
||||
UV_CLOCK_MONOTONIC,
|
||||
UV_CLOCK_REALTIME
|
||||
} uv_clock_id;
|
||||
|
||||
/* XXX(bnoordhuis) not 2038-proof, https://github.com/libuv/libuv/issues/3864 */
|
||||
typedef struct {
|
||||
long tv_sec;
|
||||
long tv_nsec;
|
||||
} uv_timespec_t;
|
||||
|
||||
typedef struct {
|
||||
int64_t tv_sec;
|
||||
int32_t tv_nsec;
|
||||
} uv_timespec64_t;
|
||||
|
||||
/* XXX(bnoordhuis) not 2038-proof, https://github.com/libuv/libuv/issues/3864 */
|
||||
typedef struct {
|
||||
long tv_sec;
|
||||
long tv_usec;
|
||||
} uv_timeval_t;
|
||||
|
||||
typedef struct {
|
||||
int64_t tv_sec;
|
||||
int32_t tv_usec;
|
||||
} uv_timeval64_t;
|
||||
|
||||
typedef struct {
|
||||
uint64_t st_dev;
|
||||
@ -437,7 +470,7 @@ struct uv_shutdown_s {
|
||||
uv_handle_type type; \
|
||||
/* private */ \
|
||||
uv_close_cb close_cb; \
|
||||
void* handle_queue[2]; \
|
||||
struct uv__queue handle_queue; \
|
||||
union { \
|
||||
int fd; \
|
||||
void* reserved[4]; \
|
||||
@ -575,7 +608,18 @@ UV_EXTERN int uv_tcp_simultaneous_accepts(uv_tcp_t* handle, int enable);
|
||||
|
||||
enum uv_tcp_flags {
|
||||
/* Used with uv_tcp_bind, when an IPv6 address is used. */
|
||||
UV_TCP_IPV6ONLY = 1
|
||||
UV_TCP_IPV6ONLY = 1,
|
||||
|
||||
/* Enable SO_REUSEPORT socket option when binding the handle.
|
||||
* This allows completely duplicate bindings by multiple processes
|
||||
* or threads if they all set SO_REUSEPORT before binding the port.
|
||||
* Incoming connections are distributed across the participating
|
||||
* listener sockets.
|
||||
*
|
||||
* This flag is available only on Linux 3.9+, DragonFlyBSD 3.6+,
|
||||
* FreeBSD 12.0+, Solaris 11.4, and AIX 7.2.5+ for now.
|
||||
*/
|
||||
UV_TCP_REUSEPORT = 2,
|
||||
};
|
||||
|
||||
UV_EXTERN int uv_tcp_bind(uv_tcp_t* handle,
|
||||
@ -616,10 +660,13 @@ enum uv_udp_flags {
|
||||
UV_UDP_PARTIAL = 2,
|
||||
/*
|
||||
* Indicates if SO_REUSEADDR will be set when binding the handle.
|
||||
* This sets the SO_REUSEPORT socket flag on the BSDs and OS X. On other
|
||||
* Unix platforms, it sets the SO_REUSEADDR flag. What that means is that
|
||||
* multiple threads or processes can bind to the same address without error
|
||||
* (provided they all set the flag) but only the last one to bind will receive
|
||||
* This sets the SO_REUSEPORT socket flag on the BSDs (except for
|
||||
* DragonFlyBSD), OS X, and other platforms where SO_REUSEPORTs don't
|
||||
* have the capability of load balancing, as the opposite of what
|
||||
* UV_UDP_REUSEPORT would do. On other Unix platforms, it sets the
|
||||
* SO_REUSEADDR flag. What that means is that multiple threads or
|
||||
* processes can bind to the same address without error (provided
|
||||
* they all set the flag) but only the last one to bind will receive
|
||||
* any traffic, in effect "stealing" the port from the previous listener.
|
||||
*/
|
||||
UV_UDP_REUSEADDR = 4,
|
||||
@ -642,6 +689,18 @@ enum uv_udp_flags {
|
||||
* This flag is no-op on platforms other than Linux.
|
||||
*/
|
||||
UV_UDP_LINUX_RECVERR = 32,
|
||||
/*
|
||||
* Indicates if SO_REUSEPORT will be set when binding the handle.
|
||||
* This sets the SO_REUSEPORT socket option on supported platforms.
|
||||
* Unlike UV_UDP_REUSEADDR, this flag will make multiple threads or
|
||||
* processes that are binding to the same address and port "share"
|
||||
* the port, which means incoming datagrams are distributed across
|
||||
* the receiving sockets among threads or processes.
|
||||
*
|
||||
* This flag is available only on Linux 3.9+, DragonFlyBSD 3.6+,
|
||||
* FreeBSD 12.0+, Solaris 11.4, and AIX 7.2.5+ for now.
|
||||
*/
|
||||
UV_UDP_REUSEPORT = 64,
|
||||
/*
|
||||
* Indicates that recvmmsg should be used, if available.
|
||||
*/
|
||||
@ -718,6 +777,12 @@ UV_EXTERN int uv_udp_try_send(uv_udp_t* handle,
|
||||
const uv_buf_t bufs[],
|
||||
unsigned int nbufs,
|
||||
const struct sockaddr* addr);
|
||||
UV_EXTERN int uv_udp_try_send2(uv_udp_t* handle,
|
||||
unsigned int count,
|
||||
uv_buf_t* bufs[/*count*/],
|
||||
unsigned int nbufs[/*count*/],
|
||||
struct sockaddr* addrs[/*count*/],
|
||||
unsigned int flags);
|
||||
UV_EXTERN int uv_udp_recv_start(uv_udp_t* handle,
|
||||
uv_alloc_cb alloc_cb,
|
||||
uv_udp_recv_cb recv_cb);
|
||||
@ -741,10 +806,15 @@ struct uv_tty_s {
|
||||
typedef enum {
|
||||
/* Initial/normal terminal mode */
|
||||
UV_TTY_MODE_NORMAL,
|
||||
/* Raw input mode (On Windows, ENABLE_WINDOW_INPUT is also enabled) */
|
||||
/*
|
||||
* Raw input mode (On Windows, ENABLE_WINDOW_INPUT is also enabled).
|
||||
* May become equivalent to UV_TTY_MODE_RAW_VT in future libuv versions.
|
||||
*/
|
||||
UV_TTY_MODE_RAW,
|
||||
/* Binary-safe I/O mode for IPC (Unix-only) */
|
||||
UV_TTY_MODE_IO
|
||||
UV_TTY_MODE_IO,
|
||||
/* Raw input mode. On Windows ENABLE_VIRTUAL_TERMINAL_INPUT is also set. */
|
||||
UV_TTY_MODE_RAW_VT
|
||||
} uv_tty_mode_t;
|
||||
|
||||
typedef enum {
|
||||
@ -779,6 +849,10 @@ inline int uv_tty_set_mode(uv_tty_t* handle, int mode) {
|
||||
|
||||
UV_EXTERN uv_handle_type uv_guess_handle(uv_file file);
|
||||
|
||||
enum {
|
||||
UV_PIPE_NO_TRUNCATE = 1u << 0
|
||||
};
|
||||
|
||||
/*
|
||||
* uv_pipe_t is a subclass of uv_stream_t.
|
||||
*
|
||||
@ -795,10 +869,20 @@ struct uv_pipe_s {
|
||||
UV_EXTERN int uv_pipe_init(uv_loop_t*, uv_pipe_t* handle, int ipc);
|
||||
UV_EXTERN int uv_pipe_open(uv_pipe_t*, uv_file file);
|
||||
UV_EXTERN int uv_pipe_bind(uv_pipe_t* handle, const char* name);
|
||||
UV_EXTERN int uv_pipe_bind2(uv_pipe_t* handle,
|
||||
const char* name,
|
||||
size_t namelen,
|
||||
unsigned int flags);
|
||||
UV_EXTERN void uv_pipe_connect(uv_connect_t* req,
|
||||
uv_pipe_t* handle,
|
||||
const char* name,
|
||||
uv_connect_cb cb);
|
||||
UV_EXTERN int uv_pipe_connect2(uv_connect_t* req,
|
||||
uv_pipe_t* handle,
|
||||
const char* name,
|
||||
size_t namelen,
|
||||
unsigned int flags,
|
||||
uv_connect_cb cb);
|
||||
UV_EXTERN int uv_pipe_getsockname(const uv_pipe_t* handle,
|
||||
char* buffer,
|
||||
size_t* size);
|
||||
@ -1063,7 +1147,14 @@ enum uv_process_flags {
|
||||
* option is only meaningful on Windows systems. On Unix it is silently
|
||||
* ignored.
|
||||
*/
|
||||
UV_PROCESS_WINDOWS_HIDE_GUI = (1 << 6)
|
||||
UV_PROCESS_WINDOWS_HIDE_GUI = (1 << 6),
|
||||
/*
|
||||
* On Windows, if the path to the program to execute, specified in
|
||||
* uv_process_options_t's file field, has a directory component,
|
||||
* search for the exact file name before trying variants with
|
||||
* extensions like '.exe' or '.cmd'.
|
||||
*/
|
||||
UV_PROCESS_WINDOWS_FILE_PATH_EXACT_NAME = (1 << 7)
|
||||
};
|
||||
|
||||
/*
|
||||
@ -1133,12 +1224,18 @@ struct uv_interface_address_s {
|
||||
|
||||
struct uv_passwd_s {
|
||||
char* username;
|
||||
long uid;
|
||||
long gid;
|
||||
unsigned long uid;
|
||||
unsigned long gid;
|
||||
char* shell;
|
||||
char* homedir;
|
||||
};
|
||||
|
||||
struct uv_group_s {
|
||||
char* groupname;
|
||||
unsigned long gid;
|
||||
char** members;
|
||||
};
|
||||
|
||||
struct uv_utsname_s {
|
||||
char sysname[256];
|
||||
char release[256];
|
||||
@ -1184,16 +1281,6 @@ UV_EXTERN int uv_uptime(double* uptime);
|
||||
UV_EXTERN uv_os_fd_t uv_get_osfhandle(int fd);
|
||||
UV_EXTERN int uv_open_osfhandle(uv_os_fd_t os_fd);
|
||||
|
||||
typedef struct {
|
||||
long tv_sec;
|
||||
long tv_usec;
|
||||
} uv_timeval_t;
|
||||
|
||||
typedef struct {
|
||||
int64_t tv_sec;
|
||||
int32_t tv_usec;
|
||||
} uv_timeval64_t;
|
||||
|
||||
typedef struct {
|
||||
uv_timeval_t ru_utime; /* user CPU time used */
|
||||
uv_timeval_t ru_stime; /* system CPU time used */
|
||||
@ -1214,11 +1301,15 @@ typedef struct {
|
||||
} uv_rusage_t;
|
||||
|
||||
UV_EXTERN int uv_getrusage(uv_rusage_t* rusage);
|
||||
UV_EXTERN int uv_getrusage_thread(uv_rusage_t* rusage);
|
||||
|
||||
UV_EXTERN int uv_os_homedir(char* buffer, size_t* size);
|
||||
UV_EXTERN int uv_os_tmpdir(char* buffer, size_t* size);
|
||||
UV_EXTERN int uv_os_get_passwd(uv_passwd_t* pwd);
|
||||
UV_EXTERN void uv_os_free_passwd(uv_passwd_t* pwd);
|
||||
UV_EXTERN int uv_os_get_passwd2(uv_passwd_t* pwd, uv_uid_t uid);
|
||||
UV_EXTERN int uv_os_get_group(uv_group_t* grp, uv_uid_t gid);
|
||||
UV_EXTERN void uv_os_free_group(uv_group_t* grp);
|
||||
UV_EXTERN uv_pid_t uv_os_getpid(void);
|
||||
UV_EXTERN uv_pid_t uv_os_getppid(void);
|
||||
|
||||
@ -1242,8 +1333,21 @@ UV_EXTERN uv_pid_t uv_os_getppid(void);
|
||||
UV_EXTERN int uv_os_getpriority(uv_pid_t pid, int* priority);
|
||||
UV_EXTERN int uv_os_setpriority(uv_pid_t pid, int priority);
|
||||
|
||||
enum {
|
||||
UV_THREAD_PRIORITY_HIGHEST = 2,
|
||||
UV_THREAD_PRIORITY_ABOVE_NORMAL = 1,
|
||||
UV_THREAD_PRIORITY_NORMAL = 0,
|
||||
UV_THREAD_PRIORITY_BELOW_NORMAL = -1,
|
||||
UV_THREAD_PRIORITY_LOWEST = -2,
|
||||
};
|
||||
|
||||
UV_EXTERN int uv_thread_getpriority(uv_thread_t tid, int* priority);
|
||||
UV_EXTERN int uv_thread_setpriority(uv_thread_t tid, int priority);
|
||||
|
||||
UV_EXTERN unsigned int uv_available_parallelism(void);
|
||||
UV_EXTERN int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count);
|
||||
UV_EXTERN void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count);
|
||||
UV_EXTERN int uv_cpumask_size(void);
|
||||
|
||||
UV_EXTERN int uv_interface_addresses(uv_interface_address_t** addresses,
|
||||
int* count);
|
||||
@ -1276,6 +1380,15 @@ UV_EXTERN int uv_os_gethostname(char* buffer, size_t* size);
|
||||
|
||||
UV_EXTERN int uv_os_uname(uv_utsname_t* buffer);
|
||||
|
||||
struct uv_metrics_s {
|
||||
uint64_t loop_count;
|
||||
uint64_t events;
|
||||
uint64_t events_waiting;
|
||||
/* private */
|
||||
uint64_t* reserved[13];
|
||||
};
|
||||
|
||||
UV_EXTERN int uv_metrics_info(uv_loop_t* loop, uv_metrics_t* metrics);
|
||||
UV_EXTERN uint64_t uv_metrics_idle_time(uv_loop_t* loop);
|
||||
|
||||
typedef enum {
|
||||
@ -1478,6 +1591,8 @@ UV_EXTERN int uv_fs_chmod(uv_loop_t* loop,
|
||||
const char* path,
|
||||
int mode,
|
||||
uv_fs_cb cb);
|
||||
#define UV_FS_UTIME_NOW (INFINITY)
|
||||
#define UV_FS_UTIME_OMIT (NAN)
|
||||
UV_EXTERN int uv_fs_utime(uv_loop_t* loop,
|
||||
uv_fs_t* req,
|
||||
const char* path,
|
||||
@ -1709,7 +1824,9 @@ UV_EXTERN int uv_chdir(const char* dir);
|
||||
UV_EXTERN uint64_t uv_get_free_memory(void);
|
||||
UV_EXTERN uint64_t uv_get_total_memory(void);
|
||||
UV_EXTERN uint64_t uv_get_constrained_memory(void);
|
||||
UV_EXTERN uint64_t uv_get_available_memory(void);
|
||||
|
||||
UV_EXTERN int uv_clock_gettime(uv_clock_id clock_id, uv_timespec64_t* ts);
|
||||
UV_EXTERN uint64_t uv_hrtime(void);
|
||||
UV_EXTERN void uv_sleep(unsigned int msec);
|
||||
|
||||
@ -1768,6 +1885,7 @@ UV_EXTERN int uv_gettimeofday(uv_timeval64_t* tv);
|
||||
typedef void (*uv_thread_cb)(void* arg);
|
||||
|
||||
UV_EXTERN int uv_thread_create(uv_thread_t* tid, uv_thread_cb entry, void* arg);
|
||||
UV_EXTERN int uv_thread_detach(uv_thread_t* tid);
|
||||
|
||||
typedef enum {
|
||||
UV_THREAD_NO_FLAGS = 0x00,
|
||||
@ -1786,9 +1904,20 @@ UV_EXTERN int uv_thread_create_ex(uv_thread_t* tid,
|
||||
const uv_thread_options_t* params,
|
||||
uv_thread_cb entry,
|
||||
void* arg);
|
||||
UV_EXTERN int uv_thread_setaffinity(uv_thread_t* tid,
|
||||
char* cpumask,
|
||||
char* oldmask,
|
||||
size_t mask_size);
|
||||
UV_EXTERN int uv_thread_getaffinity(uv_thread_t* tid,
|
||||
char* cpumask,
|
||||
size_t mask_size);
|
||||
UV_EXTERN int uv_thread_getcpu(void);
|
||||
UV_EXTERN uv_thread_t uv_thread_self(void);
|
||||
UV_EXTERN int uv_thread_join(uv_thread_t *tid);
|
||||
UV_EXTERN int uv_thread_equal(const uv_thread_t* t1, const uv_thread_t* t2);
|
||||
UV_EXTERN int uv_thread_setname(const char* name);
|
||||
UV_EXTERN int uv_thread_getname(uv_thread_t* tid, char* name, size_t size);
|
||||
|
||||
|
||||
/* The presence of these unions force similar struct layout. */
|
||||
#define XX(_, name) uv_ ## name ## _t name;
|
||||
@ -1807,7 +1936,7 @@ struct uv_loop_s {
|
||||
void* data;
|
||||
/* Loop reference counting. */
|
||||
unsigned int active_handles;
|
||||
void* handle_queue[2];
|
||||
struct uv__queue handle_queue;
|
||||
union {
|
||||
void* unused;
|
||||
unsigned int count;
|
||||
@ -1822,6 +1951,18 @@ struct uv_loop_s {
|
||||
UV_EXTERN void* uv_loop_get_data(const uv_loop_t*);
|
||||
UV_EXTERN void uv_loop_set_data(uv_loop_t*, void* data);
|
||||
|
||||
/* Unicode utilities needed for dealing with Windows. */
|
||||
UV_EXTERN size_t uv_utf16_length_as_wtf8(const uint16_t* utf16,
|
||||
ssize_t utf16_len);
|
||||
UV_EXTERN int uv_utf16_to_wtf8(const uint16_t* utf16,
|
||||
ssize_t utf16_len,
|
||||
char** wtf8_ptr,
|
||||
size_t* wtf8_len_ptr);
|
||||
UV_EXTERN ssize_t uv_wtf8_length_as_utf16(const char* wtf8);
|
||||
UV_EXTERN void uv_wtf8_to_utf16(const char* wtf8,
|
||||
uint16_t* utf16,
|
||||
size_t utf16_len);
|
||||
|
||||
/* Don't export the private CPP symbols. */
|
||||
#undef UV_HANDLE_TYPE_PRIVATE
|
||||
#undef UV_REQ_TYPE_PRIVATE
|
||||
|
||||
@ -1,54 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1995, 1999
|
||||
* Berkeley Software Design, Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* BSDI ifaddrs.h,v 2.5 2000/02/23 14:51:59 dab Exp
|
||||
*/
|
||||
|
||||
#ifndef _IFADDRS_H_
|
||||
#define _IFADDRS_H_
|
||||
|
||||
struct ifaddrs {
|
||||
struct ifaddrs *ifa_next;
|
||||
char *ifa_name;
|
||||
unsigned int ifa_flags;
|
||||
struct sockaddr *ifa_addr;
|
||||
struct sockaddr *ifa_netmask;
|
||||
struct sockaddr *ifa_dstaddr;
|
||||
void *ifa_data;
|
||||
};
|
||||
|
||||
/*
|
||||
* This may have been defined in <net/if.h>. Note that if <net/if.h> is
|
||||
* to be included it must be included before this header file.
|
||||
*/
|
||||
#ifndef ifa_broadaddr
|
||||
#define ifa_broadaddr ifa_dstaddr /* broadcast address interface */
|
||||
#endif
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
extern int getifaddrs(struct ifaddrs **ifap);
|
||||
extern void freeifaddrs(struct ifaddrs *ifa);
|
||||
__END_DECLS
|
||||
|
||||
#endif
|
||||
@ -40,7 +40,7 @@
|
||||
void* cf_state; \
|
||||
uv_mutex_t cf_mutex; \
|
||||
uv_sem_t cf_sem; \
|
||||
void* cf_signals[2]; \
|
||||
struct uv__queue cf_signals; \
|
||||
|
||||
#define UV_PLATFORM_FS_EVENT_FIELDS \
|
||||
uv__io_t event_watcher; \
|
||||
@ -48,8 +48,8 @@
|
||||
int realpath_len; \
|
||||
int cf_flags; \
|
||||
uv_async_t* cf_cb; \
|
||||
void* cf_events[2]; \
|
||||
void* cf_member[2]; \
|
||||
struct uv__queue cf_events; \
|
||||
struct uv__queue cf_member; \
|
||||
int cf_error; \
|
||||
uv_mutex_t cf_mutex; \
|
||||
|
||||
|
||||
@ -413,7 +413,6 @@
|
||||
#elif defined(__APPLE__) || \
|
||||
defined(__DragonFly__) || \
|
||||
defined(__FreeBSD__) || \
|
||||
defined(__FreeBSD_kernel__) || \
|
||||
defined(__NetBSD__) || \
|
||||
defined(__OpenBSD__)
|
||||
# define UV__EHOSTDOWN (-64)
|
||||
@ -457,4 +456,28 @@
|
||||
# define UV__ESOCKTNOSUPPORT (-4025)
|
||||
#endif
|
||||
|
||||
/* FreeBSD defines ENODATA in /usr/include/c++/v1/errno.h which is only visible
|
||||
* if C++ is being used. Define it directly to avoid problems when integrating
|
||||
* libuv in a C++ project.
|
||||
*/
|
||||
#if defined(ENODATA) && !defined(_WIN32)
|
||||
# define UV__ENODATA UV__ERR(ENODATA)
|
||||
#elif defined(__FreeBSD__)
|
||||
# define UV__ENODATA (-9919)
|
||||
#else
|
||||
# define UV__ENODATA (-4024)
|
||||
#endif
|
||||
|
||||
#if defined(EUNATCH) && !defined(_WIN32)
|
||||
# define UV__EUNATCH UV__ERR(EUNATCH)
|
||||
#else
|
||||
# define UV__EUNATCH (-4023)
|
||||
#endif
|
||||
|
||||
#if defined(ENOEXEC) && !defined(_WIN32)
|
||||
# define UV__ENOEXEC UV__ERR(ENOEXEC)
|
||||
#else
|
||||
# define UV__ENOEXEC (-4022)
|
||||
#endif
|
||||
|
||||
#endif /* UV_ERRNO_H_ */
|
||||
|
||||
@ -28,7 +28,7 @@
|
||||
int inotify_fd; \
|
||||
|
||||
#define UV_PLATFORM_FS_EVENT_FIELDS \
|
||||
void* watchers[2]; \
|
||||
struct uv__queue watchers; \
|
||||
int wd; \
|
||||
|
||||
#endif /* UV_LINUX_H */
|
||||
|
||||
@ -1,247 +0,0 @@
|
||||
// ISO C9x compliant stdint.h for Microsoft Visual Studio
|
||||
// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
|
||||
//
|
||||
// Copyright (c) 2006-2008 Alexander Chemeris
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. The name of the author may be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _MSC_VER // [
|
||||
#error "Use this header only with Microsoft Visual C++ compilers!"
|
||||
#endif // _MSC_VER ]
|
||||
|
||||
#ifndef _MSC_STDINT_H_ // [
|
||||
#define _MSC_STDINT_H_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
// For Visual Studio 6 in C++ mode and for many Visual Studio versions when
|
||||
// compiling for ARM we should wrap <wchar.h> include with 'extern "C++" {}'
|
||||
// or compiler give many errors like this:
|
||||
// error C2733: second C linkage of overloaded function 'wmemchr' not allowed
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
# include <wchar.h>
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
// Define _W64 macros to mark types changing their size, like intptr_t.
|
||||
#ifndef _W64
|
||||
# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300
|
||||
# define _W64 __w64
|
||||
# else
|
||||
# define _W64
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
// 7.18.1 Integer types
|
||||
|
||||
// 7.18.1.1 Exact-width integer types
|
||||
|
||||
// Visual Studio 6 and Embedded Visual C++ 4 doesn't
|
||||
// realize that, e.g. char has the same size as __int8
|
||||
// so we give up on __intX for them.
|
||||
#if (_MSC_VER < 1300)
|
||||
typedef signed char int8_t;
|
||||
typedef signed short int16_t;
|
||||
typedef signed int int32_t;
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned int uint32_t;
|
||||
#else
|
||||
typedef signed __int8 int8_t;
|
||||
typedef signed __int16 int16_t;
|
||||
typedef signed __int32 int32_t;
|
||||
typedef unsigned __int8 uint8_t;
|
||||
typedef unsigned __int16 uint16_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
#endif
|
||||
typedef signed __int64 int64_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
|
||||
|
||||
// 7.18.1.2 Minimum-width integer types
|
||||
typedef int8_t int_least8_t;
|
||||
typedef int16_t int_least16_t;
|
||||
typedef int32_t int_least32_t;
|
||||
typedef int64_t int_least64_t;
|
||||
typedef uint8_t uint_least8_t;
|
||||
typedef uint16_t uint_least16_t;
|
||||
typedef uint32_t uint_least32_t;
|
||||
typedef uint64_t uint_least64_t;
|
||||
|
||||
// 7.18.1.3 Fastest minimum-width integer types
|
||||
typedef int8_t int_fast8_t;
|
||||
typedef int16_t int_fast16_t;
|
||||
typedef int32_t int_fast32_t;
|
||||
typedef int64_t int_fast64_t;
|
||||
typedef uint8_t uint_fast8_t;
|
||||
typedef uint16_t uint_fast16_t;
|
||||
typedef uint32_t uint_fast32_t;
|
||||
typedef uint64_t uint_fast64_t;
|
||||
|
||||
// 7.18.1.4 Integer types capable of holding object pointers
|
||||
#ifdef _WIN64 // [
|
||||
typedef signed __int64 intptr_t;
|
||||
typedef unsigned __int64 uintptr_t;
|
||||
#else // _WIN64 ][
|
||||
typedef _W64 signed int intptr_t;
|
||||
typedef _W64 unsigned int uintptr_t;
|
||||
#endif // _WIN64 ]
|
||||
|
||||
// 7.18.1.5 Greatest-width integer types
|
||||
typedef int64_t intmax_t;
|
||||
typedef uint64_t uintmax_t;
|
||||
|
||||
|
||||
// 7.18.2 Limits of specified-width integer types
|
||||
|
||||
#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259
|
||||
|
||||
// 7.18.2.1 Limits of exact-width integer types
|
||||
#define INT8_MIN ((int8_t)_I8_MIN)
|
||||
#define INT8_MAX _I8_MAX
|
||||
#define INT16_MIN ((int16_t)_I16_MIN)
|
||||
#define INT16_MAX _I16_MAX
|
||||
#define INT32_MIN ((int32_t)_I32_MIN)
|
||||
#define INT32_MAX _I32_MAX
|
||||
#define INT64_MIN ((int64_t)_I64_MIN)
|
||||
#define INT64_MAX _I64_MAX
|
||||
#define UINT8_MAX _UI8_MAX
|
||||
#define UINT16_MAX _UI16_MAX
|
||||
#define UINT32_MAX _UI32_MAX
|
||||
#define UINT64_MAX _UI64_MAX
|
||||
|
||||
// 7.18.2.2 Limits of minimum-width integer types
|
||||
#define INT_LEAST8_MIN INT8_MIN
|
||||
#define INT_LEAST8_MAX INT8_MAX
|
||||
#define INT_LEAST16_MIN INT16_MIN
|
||||
#define INT_LEAST16_MAX INT16_MAX
|
||||
#define INT_LEAST32_MIN INT32_MIN
|
||||
#define INT_LEAST32_MAX INT32_MAX
|
||||
#define INT_LEAST64_MIN INT64_MIN
|
||||
#define INT_LEAST64_MAX INT64_MAX
|
||||
#define UINT_LEAST8_MAX UINT8_MAX
|
||||
#define UINT_LEAST16_MAX UINT16_MAX
|
||||
#define UINT_LEAST32_MAX UINT32_MAX
|
||||
#define UINT_LEAST64_MAX UINT64_MAX
|
||||
|
||||
// 7.18.2.3 Limits of fastest minimum-width integer types
|
||||
#define INT_FAST8_MIN INT8_MIN
|
||||
#define INT_FAST8_MAX INT8_MAX
|
||||
#define INT_FAST16_MIN INT16_MIN
|
||||
#define INT_FAST16_MAX INT16_MAX
|
||||
#define INT_FAST32_MIN INT32_MIN
|
||||
#define INT_FAST32_MAX INT32_MAX
|
||||
#define INT_FAST64_MIN INT64_MIN
|
||||
#define INT_FAST64_MAX INT64_MAX
|
||||
#define UINT_FAST8_MAX UINT8_MAX
|
||||
#define UINT_FAST16_MAX UINT16_MAX
|
||||
#define UINT_FAST32_MAX UINT32_MAX
|
||||
#define UINT_FAST64_MAX UINT64_MAX
|
||||
|
||||
// 7.18.2.4 Limits of integer types capable of holding object pointers
|
||||
#ifdef _WIN64 // [
|
||||
# define INTPTR_MIN INT64_MIN
|
||||
# define INTPTR_MAX INT64_MAX
|
||||
# define UINTPTR_MAX UINT64_MAX
|
||||
#else // _WIN64 ][
|
||||
# define INTPTR_MIN INT32_MIN
|
||||
# define INTPTR_MAX INT32_MAX
|
||||
# define UINTPTR_MAX UINT32_MAX
|
||||
#endif // _WIN64 ]
|
||||
|
||||
// 7.18.2.5 Limits of greatest-width integer types
|
||||
#define INTMAX_MIN INT64_MIN
|
||||
#define INTMAX_MAX INT64_MAX
|
||||
#define UINTMAX_MAX UINT64_MAX
|
||||
|
||||
// 7.18.3 Limits of other integer types
|
||||
|
||||
#ifdef _WIN64 // [
|
||||
# define PTRDIFF_MIN _I64_MIN
|
||||
# define PTRDIFF_MAX _I64_MAX
|
||||
#else // _WIN64 ][
|
||||
# define PTRDIFF_MIN _I32_MIN
|
||||
# define PTRDIFF_MAX _I32_MAX
|
||||
#endif // _WIN64 ]
|
||||
|
||||
#define SIG_ATOMIC_MIN INT_MIN
|
||||
#define SIG_ATOMIC_MAX INT_MAX
|
||||
|
||||
#ifndef SIZE_MAX // [
|
||||
# ifdef _WIN64 // [
|
||||
# define SIZE_MAX _UI64_MAX
|
||||
# else // _WIN64 ][
|
||||
# define SIZE_MAX _UI32_MAX
|
||||
# endif // _WIN64 ]
|
||||
#endif // SIZE_MAX ]
|
||||
|
||||
// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h>
|
||||
#ifndef WCHAR_MIN // [
|
||||
# define WCHAR_MIN 0
|
||||
#endif // WCHAR_MIN ]
|
||||
#ifndef WCHAR_MAX // [
|
||||
# define WCHAR_MAX _UI16_MAX
|
||||
#endif // WCHAR_MAX ]
|
||||
|
||||
#define WINT_MIN 0
|
||||
#define WINT_MAX _UI16_MAX
|
||||
|
||||
#endif // __STDC_LIMIT_MACROS ]
|
||||
|
||||
|
||||
// 7.18.4 Limits of other integer types
|
||||
|
||||
#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260
|
||||
|
||||
// 7.18.4.1 Macros for minimum-width integer constants
|
||||
|
||||
#define INT8_C(val) val##i8
|
||||
#define INT16_C(val) val##i16
|
||||
#define INT32_C(val) val##i32
|
||||
#define INT64_C(val) val##i64
|
||||
|
||||
#define UINT8_C(val) val##ui8
|
||||
#define UINT16_C(val) val##ui16
|
||||
#define UINT32_C(val) val##ui32
|
||||
#define UINT64_C(val) val##ui64
|
||||
|
||||
// 7.18.4.2 Macros for greatest-width integer constants
|
||||
#define INTMAX_C INT64_C
|
||||
#define UINTMAX_C UINT64_C
|
||||
|
||||
#endif // __STDC_CONSTANT_MACROS ]
|
||||
|
||||
|
||||
#endif // _MSC_STDINT_H_ ]
|
||||
@ -31,7 +31,7 @@ struct uv__work {
|
||||
void (*work)(struct uv__work *w);
|
||||
void (*done)(struct uv__work *w, int status);
|
||||
struct uv_loop_s* loop;
|
||||
void* wq[2];
|
||||
struct uv__queue wq;
|
||||
};
|
||||
|
||||
#endif /* UV_THREADPOOL_H_ */
|
||||
|
||||
@ -35,21 +35,7 @@
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This file defines data structures for different types of trees:
|
||||
* splay trees and red-black trees.
|
||||
*
|
||||
* A splay tree is a self-organizing data structure. Every operation
|
||||
* on the tree causes a splay to happen. The splay moves the requested
|
||||
* node to the root of the tree and partly rebalances it.
|
||||
*
|
||||
* This has the benefit that request locality causes faster lookups as
|
||||
* the requested nodes move to the top of the tree. On the other hand,
|
||||
* every lookup causes memory writes.
|
||||
*
|
||||
* The Balance Theorem bounds the total access time for m operations
|
||||
* and n inserts on an initially empty tree as O((m + n)lg n). The
|
||||
* amortized cost for a sequence of m accesses to a splay tree is O(lg n);
|
||||
*
|
||||
* This file defines data structures for red-black trees.
|
||||
* A red-black tree is a binary search tree with the node color as an
|
||||
* extra attribute. It fulfills a set of conditions:
|
||||
* - every search path from the root to a leaf consists of the
|
||||
@ -61,239 +47,6 @@
|
||||
* The maximum height of a red-black tree is 2lg (n+1).
|
||||
*/
|
||||
|
||||
#define SPLAY_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *sph_root; /* root of the tree */ \
|
||||
}
|
||||
|
||||
#define SPLAY_INITIALIZER(root) \
|
||||
{ NULL }
|
||||
|
||||
#define SPLAY_INIT(root) do { \
|
||||
(root)->sph_root = NULL; \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
#define SPLAY_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *spe_left; /* left element */ \
|
||||
struct type *spe_right; /* right element */ \
|
||||
}
|
||||
|
||||
#define SPLAY_LEFT(elm, field) (elm)->field.spe_left
|
||||
#define SPLAY_RIGHT(elm, field) (elm)->field.spe_right
|
||||
#define SPLAY_ROOT(head) (head)->sph_root
|
||||
#define SPLAY_EMPTY(head) (SPLAY_ROOT(head) == NULL)
|
||||
|
||||
/* SPLAY_ROTATE_{LEFT,RIGHT} expect that tmp hold SPLAY_{RIGHT,LEFT} */
|
||||
#define SPLAY_ROTATE_RIGHT(head, tmp, field) do { \
|
||||
SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(tmp, field); \
|
||||
SPLAY_RIGHT(tmp, field) = (head)->sph_root; \
|
||||
(head)->sph_root = tmp; \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
#define SPLAY_ROTATE_LEFT(head, tmp, field) do { \
|
||||
SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(tmp, field); \
|
||||
SPLAY_LEFT(tmp, field) = (head)->sph_root; \
|
||||
(head)->sph_root = tmp; \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
#define SPLAY_LINKLEFT(head, tmp, field) do { \
|
||||
SPLAY_LEFT(tmp, field) = (head)->sph_root; \
|
||||
tmp = (head)->sph_root; \
|
||||
(head)->sph_root = SPLAY_LEFT((head)->sph_root, field); \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
#define SPLAY_LINKRIGHT(head, tmp, field) do { \
|
||||
SPLAY_RIGHT(tmp, field) = (head)->sph_root; \
|
||||
tmp = (head)->sph_root; \
|
||||
(head)->sph_root = SPLAY_RIGHT((head)->sph_root, field); \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
#define SPLAY_ASSEMBLE(head, node, left, right, field) do { \
|
||||
SPLAY_RIGHT(left, field) = SPLAY_LEFT((head)->sph_root, field); \
|
||||
SPLAY_LEFT(right, field) = SPLAY_RIGHT((head)->sph_root, field); \
|
||||
SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(node, field); \
|
||||
SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(node, field); \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
/* Generates prototypes and inline functions */
|
||||
|
||||
#define SPLAY_PROTOTYPE(name, type, field, cmp) \
|
||||
void name##_SPLAY(struct name *, struct type *); \
|
||||
void name##_SPLAY_MINMAX(struct name *, int); \
|
||||
struct type *name##_SPLAY_INSERT(struct name *, struct type *); \
|
||||
struct type *name##_SPLAY_REMOVE(struct name *, struct type *); \
|
||||
\
|
||||
/* Finds the node with the same key as elm */ \
|
||||
static __inline struct type * \
|
||||
name##_SPLAY_FIND(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
if (SPLAY_EMPTY(head)) \
|
||||
return(NULL); \
|
||||
name##_SPLAY(head, elm); \
|
||||
if ((cmp)(elm, (head)->sph_root) == 0) \
|
||||
return (head->sph_root); \
|
||||
return (NULL); \
|
||||
} \
|
||||
\
|
||||
static __inline struct type * \
|
||||
name##_SPLAY_NEXT(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
name##_SPLAY(head, elm); \
|
||||
if (SPLAY_RIGHT(elm, field) != NULL) { \
|
||||
elm = SPLAY_RIGHT(elm, field); \
|
||||
while (SPLAY_LEFT(elm, field) != NULL) { \
|
||||
elm = SPLAY_LEFT(elm, field); \
|
||||
} \
|
||||
} else \
|
||||
elm = NULL; \
|
||||
return (elm); \
|
||||
} \
|
||||
\
|
||||
static __inline struct type * \
|
||||
name##_SPLAY_MIN_MAX(struct name *head, int val) \
|
||||
{ \
|
||||
name##_SPLAY_MINMAX(head, val); \
|
||||
return (SPLAY_ROOT(head)); \
|
||||
}
|
||||
|
||||
/* Main splay operation.
|
||||
* Moves node close to the key of elm to top
|
||||
*/
|
||||
#define SPLAY_GENERATE(name, type, field, cmp) \
|
||||
struct type * \
|
||||
name##_SPLAY_INSERT(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
if (SPLAY_EMPTY(head)) { \
|
||||
SPLAY_LEFT(elm, field) = SPLAY_RIGHT(elm, field) = NULL; \
|
||||
} else { \
|
||||
int __comp; \
|
||||
name##_SPLAY(head, elm); \
|
||||
__comp = (cmp)(elm, (head)->sph_root); \
|
||||
if(__comp < 0) { \
|
||||
SPLAY_LEFT(elm, field) = SPLAY_LEFT((head)->sph_root, field); \
|
||||
SPLAY_RIGHT(elm, field) = (head)->sph_root; \
|
||||
SPLAY_LEFT((head)->sph_root, field) = NULL; \
|
||||
} else if (__comp > 0) { \
|
||||
SPLAY_RIGHT(elm, field) = SPLAY_RIGHT((head)->sph_root, field); \
|
||||
SPLAY_LEFT(elm, field) = (head)->sph_root; \
|
||||
SPLAY_RIGHT((head)->sph_root, field) = NULL; \
|
||||
} else \
|
||||
return ((head)->sph_root); \
|
||||
} \
|
||||
(head)->sph_root = (elm); \
|
||||
return (NULL); \
|
||||
} \
|
||||
\
|
||||
struct type * \
|
||||
name##_SPLAY_REMOVE(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
struct type *__tmp; \
|
||||
if (SPLAY_EMPTY(head)) \
|
||||
return (NULL); \
|
||||
name##_SPLAY(head, elm); \
|
||||
if ((cmp)(elm, (head)->sph_root) == 0) { \
|
||||
if (SPLAY_LEFT((head)->sph_root, field) == NULL) { \
|
||||
(head)->sph_root = SPLAY_RIGHT((head)->sph_root, field); \
|
||||
} else { \
|
||||
__tmp = SPLAY_RIGHT((head)->sph_root, field); \
|
||||
(head)->sph_root = SPLAY_LEFT((head)->sph_root, field); \
|
||||
name##_SPLAY(head, elm); \
|
||||
SPLAY_RIGHT((head)->sph_root, field) = __tmp; \
|
||||
} \
|
||||
return (elm); \
|
||||
} \
|
||||
return (NULL); \
|
||||
} \
|
||||
\
|
||||
void \
|
||||
name##_SPLAY(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
struct type __node, *__left, *__right, *__tmp; \
|
||||
int __comp; \
|
||||
\
|
||||
SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL; \
|
||||
__left = __right = &__node; \
|
||||
\
|
||||
while ((__comp = (cmp)(elm, (head)->sph_root)) != 0) { \
|
||||
if (__comp < 0) { \
|
||||
__tmp = SPLAY_LEFT((head)->sph_root, field); \
|
||||
if (__tmp == NULL) \
|
||||
break; \
|
||||
if ((cmp)(elm, __tmp) < 0){ \
|
||||
SPLAY_ROTATE_RIGHT(head, __tmp, field); \
|
||||
if (SPLAY_LEFT((head)->sph_root, field) == NULL) \
|
||||
break; \
|
||||
} \
|
||||
SPLAY_LINKLEFT(head, __right, field); \
|
||||
} else if (__comp > 0) { \
|
||||
__tmp = SPLAY_RIGHT((head)->sph_root, field); \
|
||||
if (__tmp == NULL) \
|
||||
break; \
|
||||
if ((cmp)(elm, __tmp) > 0){ \
|
||||
SPLAY_ROTATE_LEFT(head, __tmp, field); \
|
||||
if (SPLAY_RIGHT((head)->sph_root, field) == NULL) \
|
||||
break; \
|
||||
} \
|
||||
SPLAY_LINKRIGHT(head, __left, field); \
|
||||
} \
|
||||
} \
|
||||
SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \
|
||||
} \
|
||||
\
|
||||
/* Splay with either the minimum or the maximum element \
|
||||
* Used to find minimum or maximum element in tree. \
|
||||
*/ \
|
||||
void name##_SPLAY_MINMAX(struct name *head, int __comp) \
|
||||
{ \
|
||||
struct type __node, *__left, *__right, *__tmp; \
|
||||
\
|
||||
SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL; \
|
||||
__left = __right = &__node; \
|
||||
\
|
||||
for (;;) { \
|
||||
if (__comp < 0) { \
|
||||
__tmp = SPLAY_LEFT((head)->sph_root, field); \
|
||||
if (__tmp == NULL) \
|
||||
break; \
|
||||
if (__comp < 0){ \
|
||||
SPLAY_ROTATE_RIGHT(head, __tmp, field); \
|
||||
if (SPLAY_LEFT((head)->sph_root, field) == NULL) \
|
||||
break; \
|
||||
} \
|
||||
SPLAY_LINKLEFT(head, __right, field); \
|
||||
} else if (__comp > 0) { \
|
||||
__tmp = SPLAY_RIGHT((head)->sph_root, field); \
|
||||
if (__tmp == NULL) \
|
||||
break; \
|
||||
if (__comp > 0) { \
|
||||
SPLAY_ROTATE_LEFT(head, __tmp, field); \
|
||||
if (SPLAY_RIGHT((head)->sph_root, field) == NULL) \
|
||||
break; \
|
||||
} \
|
||||
SPLAY_LINKRIGHT(head, __left, field); \
|
||||
} \
|
||||
} \
|
||||
SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \
|
||||
}
|
||||
|
||||
#define SPLAY_NEGINF -1
|
||||
#define SPLAY_INF 1
|
||||
|
||||
#define SPLAY_INSERT(name, x, y) name##_SPLAY_INSERT(x, y)
|
||||
#define SPLAY_REMOVE(name, x, y) name##_SPLAY_REMOVE(x, y)
|
||||
#define SPLAY_FIND(name, x, y) name##_SPLAY_FIND(x, y)
|
||||
#define SPLAY_NEXT(name, x, y) name##_SPLAY_NEXT(x, y)
|
||||
#define SPLAY_MIN(name, x) (SPLAY_EMPTY(x) ? NULL \
|
||||
: name##_SPLAY_MIN_MAX(x, SPLAY_NEGINF))
|
||||
#define SPLAY_MAX(name, x) (SPLAY_EMPTY(x) ? NULL \
|
||||
: name##_SPLAY_MIN_MAX(x, SPLAY_INF))
|
||||
|
||||
#define SPLAY_FOREACH(x, name, head) \
|
||||
for ((x) = SPLAY_MIN(name, head); \
|
||||
(x) != NULL; \
|
||||
(x) = SPLAY_NEXT(name, head, x))
|
||||
|
||||
/* Macros that define a red-black tree */
|
||||
#define RB_HEAD(name, type) \
|
||||
struct name { \
|
||||
@ -730,8 +483,8 @@ name##_RB_MINMAX(struct name *head, int val) \
|
||||
#define RB_REMOVE(name, x, y) name##_RB_REMOVE(x, y)
|
||||
#define RB_FIND(name, x, y) name##_RB_FIND(x, y)
|
||||
#define RB_NFIND(name, x, y) name##_RB_NFIND(x, y)
|
||||
#define RB_NEXT(name, x, y) name##_RB_NEXT(y)
|
||||
#define RB_PREV(name, x, y) name##_RB_PREV(y)
|
||||
#define RB_NEXT(name, x) name##_RB_NEXT(x)
|
||||
#define RB_PREV(name, x) name##_RB_PREV(x)
|
||||
#define RB_MIN(name, x) name##_RB_MINMAX(x, RB_NEGINF)
|
||||
#define RB_MAX(name, x) name##_RB_MINMAX(x, RB_INF)
|
||||
|
||||
|
||||
@ -59,7 +59,6 @@
|
||||
# include "uv/darwin.h"
|
||||
#elif defined(__DragonFly__) || \
|
||||
defined(__FreeBSD__) || \
|
||||
defined(__FreeBSD_kernel__) || \
|
||||
defined(__OpenBSD__) || \
|
||||
defined(__NetBSD__)
|
||||
# include "uv/bsd.h"
|
||||
@ -93,8 +92,8 @@ typedef struct uv__io_s uv__io_t;
|
||||
|
||||
struct uv__io_s {
|
||||
uv__io_cb cb;
|
||||
void* pending_queue[2];
|
||||
void* watcher_queue[2];
|
||||
struct uv__queue pending_queue;
|
||||
struct uv__queue watcher_queue;
|
||||
unsigned int pevents; /* Pending event mask i.e. mask at next tick. */
|
||||
unsigned int events; /* Current event mask. */
|
||||
int fd;
|
||||
@ -221,21 +220,21 @@ typedef struct {
|
||||
#define UV_LOOP_PRIVATE_FIELDS \
|
||||
unsigned long flags; \
|
||||
int backend_fd; \
|
||||
void* pending_queue[2]; \
|
||||
void* watcher_queue[2]; \
|
||||
struct uv__queue pending_queue; \
|
||||
struct uv__queue watcher_queue; \
|
||||
uv__io_t** watchers; \
|
||||
unsigned int nwatchers; \
|
||||
unsigned int nfds; \
|
||||
void* wq[2]; \
|
||||
struct uv__queue wq; \
|
||||
uv_mutex_t wq_mutex; \
|
||||
uv_async_t wq_async; \
|
||||
uv_rwlock_t cloexec_lock; \
|
||||
uv_handle_t* closing_handles; \
|
||||
void* process_handles[2]; \
|
||||
void* prepare_handles[2]; \
|
||||
void* check_handles[2]; \
|
||||
void* idle_handles[2]; \
|
||||
void* async_handles[2]; \
|
||||
struct uv__queue process_handles; \
|
||||
struct uv__queue prepare_handles; \
|
||||
struct uv__queue check_handles; \
|
||||
struct uv__queue idle_handles; \
|
||||
struct uv__queue async_handles; \
|
||||
void (*async_unused)(void); /* TODO(bnoordhuis) Remove in libuv v2. */ \
|
||||
uv__io_t async_io_watcher; \
|
||||
int async_wfd; \
|
||||
@ -258,7 +257,7 @@ typedef struct {
|
||||
#define UV_PRIVATE_REQ_TYPES /* empty */
|
||||
|
||||
#define UV_WRITE_PRIVATE_FIELDS \
|
||||
void* queue[2]; \
|
||||
struct uv__queue queue; \
|
||||
unsigned int write_index; \
|
||||
uv_buf_t* bufs; \
|
||||
unsigned int nbufs; \
|
||||
@ -266,13 +265,16 @@ typedef struct {
|
||||
uv_buf_t bufsml[4]; \
|
||||
|
||||
#define UV_CONNECT_PRIVATE_FIELDS \
|
||||
void* queue[2]; \
|
||||
struct uv__queue queue; \
|
||||
|
||||
#define UV_SHUTDOWN_PRIVATE_FIELDS /* empty */
|
||||
|
||||
#define UV_UDP_SEND_PRIVATE_FIELDS \
|
||||
void* queue[2]; \
|
||||
struct sockaddr_storage addr; \
|
||||
struct uv__queue queue; \
|
||||
union { \
|
||||
struct sockaddr addr; \
|
||||
struct sockaddr_storage storage; \
|
||||
} u; \
|
||||
unsigned int nbufs; \
|
||||
uv_buf_t* bufs; \
|
||||
ssize_t status; \
|
||||
@ -287,8 +289,8 @@ typedef struct {
|
||||
uv_connect_t *connect_req; \
|
||||
uv_shutdown_t *shutdown_req; \
|
||||
uv__io_t io_watcher; \
|
||||
void* write_queue[2]; \
|
||||
void* write_completed_queue[2]; \
|
||||
struct uv__queue write_queue; \
|
||||
struct uv__queue write_completed_queue; \
|
||||
uv_connection_cb connection_cb; \
|
||||
int delayed_error; \
|
||||
int accepted_fd; \
|
||||
@ -301,35 +303,38 @@ typedef struct {
|
||||
uv_alloc_cb alloc_cb; \
|
||||
uv_udp_recv_cb recv_cb; \
|
||||
uv__io_t io_watcher; \
|
||||
void* write_queue[2]; \
|
||||
void* write_completed_queue[2]; \
|
||||
struct uv__queue write_queue; \
|
||||
struct uv__queue write_completed_queue; \
|
||||
|
||||
#define UV_PIPE_PRIVATE_FIELDS \
|
||||
const char* pipe_fname; /* strdup'ed */
|
||||
const char* pipe_fname; /* NULL or strdup'ed */
|
||||
|
||||
#define UV_POLL_PRIVATE_FIELDS \
|
||||
uv__io_t io_watcher;
|
||||
|
||||
#define UV_PREPARE_PRIVATE_FIELDS \
|
||||
uv_prepare_cb prepare_cb; \
|
||||
void* queue[2]; \
|
||||
struct uv__queue queue; \
|
||||
|
||||
#define UV_CHECK_PRIVATE_FIELDS \
|
||||
uv_check_cb check_cb; \
|
||||
void* queue[2]; \
|
||||
struct uv__queue queue; \
|
||||
|
||||
#define UV_IDLE_PRIVATE_FIELDS \
|
||||
uv_idle_cb idle_cb; \
|
||||
void* queue[2]; \
|
||||
struct uv__queue queue; \
|
||||
|
||||
#define UV_ASYNC_PRIVATE_FIELDS \
|
||||
uv_async_cb async_cb; \
|
||||
void* queue[2]; \
|
||||
struct uv__queue queue; \
|
||||
int pending; \
|
||||
|
||||
#define UV_TIMER_PRIVATE_FIELDS \
|
||||
uv_timer_cb timer_cb; \
|
||||
void* heap_node[3]; \
|
||||
union { \
|
||||
void* heap[3]; \
|
||||
struct uv__queue queue; \
|
||||
} node; \
|
||||
uint64_t timeout; \
|
||||
uint64_t repeat; \
|
||||
uint64_t start_id;
|
||||
@ -353,7 +358,7 @@ typedef struct {
|
||||
int retcode;
|
||||
|
||||
#define UV_PROCESS_PRIVATE_FIELDS \
|
||||
void* queue[2]; \
|
||||
struct uv__queue queue; \
|
||||
int status; \
|
||||
|
||||
#define UV_FS_PRIVATE_FIELDS \
|
||||
@ -418,6 +423,8 @@ typedef struct {
|
||||
# define UV_FS_O_DIRECT 0x04000
|
||||
#elif defined(__linux__) && defined(__x86_64__)
|
||||
# define UV_FS_O_DIRECT 0x04000
|
||||
#elif defined(__linux__) && defined(__loongarch__)
|
||||
# define UV_FS_O_DIRECT 0x04000
|
||||
#elif defined(O_DIRECT)
|
||||
# define UV_FS_O_DIRECT O_DIRECT
|
||||
#else
|
||||
|
||||
@ -31,10 +31,10 @@
|
||||
*/
|
||||
|
||||
#define UV_VERSION_MAJOR 1
|
||||
#define UV_VERSION_MINOR 43
|
||||
#define UV_VERSION_PATCH 0
|
||||
#define UV_VERSION_IS_RELEASE 1
|
||||
#define UV_VERSION_SUFFIX ""
|
||||
#define UV_VERSION_MINOR 50
|
||||
#define UV_VERSION_PATCH 1
|
||||
#define UV_VERSION_IS_RELEASE 0
|
||||
#define UV_VERSION_SUFFIX "dev"
|
||||
|
||||
#define UV_VERSION_HEX ((UV_VERSION_MAJOR << 16) | \
|
||||
(UV_VERSION_MINOR << 8) | \
|
||||
|
||||
@ -20,7 +20,7 @@
|
||||
*/
|
||||
|
||||
#ifndef _WIN32_WINNT
|
||||
# define _WIN32_WINNT 0x0600
|
||||
# define _WIN32_WINNT 0x0A00
|
||||
#endif
|
||||
|
||||
#if !defined(_SSIZE_T_) && !defined(_SSIZE_T_DEFINED)
|
||||
@ -32,20 +32,12 @@ typedef intptr_t ssize_t;
|
||||
|
||||
#include <winsock2.h>
|
||||
|
||||
#if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)
|
||||
typedef struct pollfd {
|
||||
SOCKET fd;
|
||||
short events;
|
||||
short revents;
|
||||
} WSAPOLLFD, *PWSAPOLLFD, *LPWSAPOLLFD;
|
||||
#endif
|
||||
|
||||
#ifndef LOCALE_INVARIANT
|
||||
# define LOCALE_INVARIANT 0x007f
|
||||
#endif
|
||||
|
||||
#include <mswsock.h>
|
||||
// Disable the typedef in mstcpip.h of MinGW.
|
||||
/* Disable the typedef in mstcpip.h of MinGW. */
|
||||
#define _TCP_INITIAL_RTO_PARAMETERS _TCP_INITIAL_RTO_PARAMETERS__AVOID
|
||||
#define TCP_INITIAL_RTO_PARAMETERS TCP_INITIAL_RTO_PARAMETERS__AVOID
|
||||
#define PTCP_INITIAL_RTO_PARAMETERS PTCP_INITIAL_RTO_PARAMETERS__AVOID
|
||||
@ -59,12 +51,7 @@ typedef struct pollfd {
|
||||
#include <signal.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1600
|
||||
# include "uv/stdint-msvc2008.h"
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#include "uv/tree.h"
|
||||
#include "uv/threadpool.h"
|
||||
@ -75,6 +62,11 @@ typedef struct pollfd {
|
||||
# define S_IFLNK 0xA000
|
||||
#endif
|
||||
|
||||
/* Define missing in Windows Kit Include\{VERSION}\ucrt\sys\stat.h */
|
||||
#if defined(_CRT_INTERNAL_NONSTDC_NAMES) && _CRT_INTERNAL_NONSTDC_NAMES && !defined(S_IFIFO)
|
||||
# define S_IFIFO _S_IFIFO
|
||||
#endif
|
||||
|
||||
/* Additional signals supported by uv_signal and or uv_kill. The CRT defines
|
||||
* the following signals already:
|
||||
*
|
||||
@ -91,6 +83,7 @@ typedef struct pollfd {
|
||||
* variants (Linux and Darwin)
|
||||
*/
|
||||
#define SIGHUP 1
|
||||
#define SIGQUIT 3
|
||||
#define SIGKILL 9
|
||||
#define SIGWINCH 28
|
||||
|
||||
@ -223,7 +216,7 @@ typedef struct _AFD_POLL_INFO {
|
||||
AFD_POLL_HANDLE_INFO Handles[1];
|
||||
} AFD_POLL_INFO, *PAFD_POLL_INFO;
|
||||
|
||||
#define UV_MSAFD_PROVIDER_COUNT 3
|
||||
#define UV_MSAFD_PROVIDER_COUNT 4
|
||||
|
||||
|
||||
/**
|
||||
@ -263,29 +256,23 @@ typedef union {
|
||||
} unused_; /* TODO: retained for ABI compatibility; remove me in v2.x. */
|
||||
} uv_cond_t;
|
||||
|
||||
typedef union {
|
||||
struct {
|
||||
unsigned int num_readers_;
|
||||
CRITICAL_SECTION num_readers_lock_;
|
||||
HANDLE write_semaphore_;
|
||||
} state_;
|
||||
/* TODO: remove me in v2.x. */
|
||||
struct {
|
||||
SRWLOCK unused_;
|
||||
} unused1_;
|
||||
/* TODO: remove me in v2.x. */
|
||||
struct {
|
||||
uv_mutex_t unused1_;
|
||||
uv_mutex_t unused2_;
|
||||
} unused2_;
|
||||
typedef struct {
|
||||
SRWLOCK read_write_lock_;
|
||||
/* TODO: retained for ABI compatibility; remove me in v2.x */
|
||||
#ifdef _WIN64
|
||||
unsigned char padding_[72];
|
||||
#else
|
||||
unsigned char padding_[44];
|
||||
#endif
|
||||
} uv_rwlock_t;
|
||||
|
||||
typedef struct {
|
||||
unsigned int n;
|
||||
unsigned int count;
|
||||
unsigned threshold;
|
||||
unsigned in;
|
||||
uv_mutex_t mutex;
|
||||
uv_sem_t turnstile1;
|
||||
uv_sem_t turnstile2;
|
||||
/* TODO: in v2 make this a uv_cond_t, without unused_ */
|
||||
CONDITION_VARIABLE cond;
|
||||
unsigned out;
|
||||
} uv_barrier_t;
|
||||
|
||||
typedef struct {
|
||||
@ -295,8 +282,8 @@ typedef struct {
|
||||
#define UV_ONCE_INIT { 0, NULL }
|
||||
|
||||
typedef struct uv_once_s {
|
||||
unsigned char ran;
|
||||
HANDLE event;
|
||||
unsigned char unused;
|
||||
INIT_ONCE init_once;
|
||||
} uv_once_t;
|
||||
|
||||
/* Platform-specific definitions for uv_spawn support. */
|
||||
@ -355,14 +342,14 @@ typedef struct {
|
||||
uv_idle_t* next_idle_handle; \
|
||||
/* This handle holds the peer sockets for the fast variant of uv_poll_t */ \
|
||||
SOCKET poll_peer_sockets[UV_MSAFD_PROVIDER_COUNT]; \
|
||||
/* Counter to keep track of active tcp streams */ \
|
||||
/* No longer used. */ \
|
||||
unsigned int active_tcp_streams; \
|
||||
/* Counter to keep track of active udp streams */ \
|
||||
/* No longer used. */ \
|
||||
unsigned int active_udp_streams; \
|
||||
/* Counter to started timer */ \
|
||||
uint64_t timer_counter; \
|
||||
/* Threadpool */ \
|
||||
void* wq[2]; \
|
||||
struct uv__queue wq; \
|
||||
uv_mutex_t wq_mutex; \
|
||||
uv_async_t wq_async;
|
||||
|
||||
@ -384,6 +371,13 @@ typedef struct {
|
||||
OVERLAPPED overlapped; \
|
||||
size_t queued_bytes; \
|
||||
} io; \
|
||||
/* in v2, we can move these to the UV_CONNECT_PRIVATE_FIELDS */ \
|
||||
struct { \
|
||||
ULONG_PTR result; /* overlapped.Internal is reused to hold the result */\
|
||||
HANDLE pipeHandle; \
|
||||
DWORD duplex_flags; \
|
||||
WCHAR* name; \
|
||||
} connect; \
|
||||
} u; \
|
||||
struct uv_req_s* next_req;
|
||||
|
||||
@ -484,7 +478,7 @@ typedef struct {
|
||||
uint32_t payload_remaining; \
|
||||
uint64_t dummy; /* TODO: retained for ABI compat; remove this in v2.x. */ \
|
||||
} ipc_data_frame; \
|
||||
void* ipc_xfer_queue[2]; \
|
||||
struct uv__queue ipc_xfer_queue; \
|
||||
int ipc_xfer_queue_length; \
|
||||
uv_write_t* non_overlapped_writes_tail; \
|
||||
CRITICAL_SECTION readfile_thread_lock; \
|
||||
@ -498,15 +492,18 @@ typedef struct {
|
||||
struct { uv_pipe_connection_fields } conn; \
|
||||
} pipe;
|
||||
|
||||
/* TODO: put the parser states in an union - TTY handles are always half-duplex
|
||||
/* TODO: put the parser states in a union - TTY handles are always half-duplex
|
||||
* so read-state can safely overlap write-state. */
|
||||
#define UV_TTY_PRIVATE_FIELDS \
|
||||
HANDLE handle; \
|
||||
union { \
|
||||
struct { \
|
||||
/* Used for readable TTY handles */ \
|
||||
union { \
|
||||
/* TODO: remove me in v2.x. */ \
|
||||
HANDLE unused_; \
|
||||
int mode; \
|
||||
} mode; \
|
||||
uv_buf_t read_line_buffer; \
|
||||
HANDLE read_raw_wait; \
|
||||
/* Fields used for translating win keystrokes into vt100 characters */ \
|
||||
@ -548,7 +545,10 @@ typedef struct {
|
||||
unsigned char events;
|
||||
|
||||
#define UV_TIMER_PRIVATE_FIELDS \
|
||||
void* heap_node[3]; \
|
||||
union { \
|
||||
void* heap[3]; \
|
||||
struct uv__queue queue; \
|
||||
} node; \
|
||||
int unused; \
|
||||
uint64_t timeout; \
|
||||
uint64_t repeat; \
|
||||
@ -606,7 +606,7 @@ typedef struct {
|
||||
struct uv_process_exit_s { \
|
||||
UV_REQ_FIELDS \
|
||||
} exit_req; \
|
||||
BYTE* child_stdio_buffer; \
|
||||
void* unused; /* TODO: retained for ABI compat; remove this in v2.x. */ \
|
||||
int exit_signal; \
|
||||
HANDLE wait_handle; \
|
||||
HANDLE process_handle; \
|
||||
|
||||
@ -8,5 +8,5 @@ Version: @PACKAGE_VERSION@
|
||||
Description: multi-platform support library with a focus on asynchronous I/O.
|
||||
URL: http://libuv.org/
|
||||
|
||||
Libs: -L${libdir} -luv_a @LIBS@
|
||||
Libs: -L${libdir} -l:libuv.a @LIBS@
|
||||
Cflags: -I${includedir}
|
||||
|
||||
@ -2,6 +2,7 @@ prefix=@prefix@
|
||||
exec_prefix=${prefix}
|
||||
libdir=@libdir@
|
||||
includedir=@includedir@
|
||||
LIBUV_STATIC=-L${libdir} -l:libuv.a @LIBS@
|
||||
|
||||
Name: libuv
|
||||
Version: @PACKAGE_VERSION@
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
dnl Macros to check the presence of generic (non-typed) symbols.
|
||||
dnl Copyright (c) 2006-2008 Diego Pettenò <flameeyes gmail com>
|
||||
dnl Copyright (c) 2006-2008 xine project
|
||||
dnl Copyright (c) 2021 libuv project
|
||||
dnl
|
||||
dnl This program is free software; you can redistribute it and/or modify
|
||||
dnl it under the terms of the GNU General Public License as published by
|
||||
@ -63,7 +64,7 @@ AC_DEFUN([CC_CHECK_CFLAGS], [
|
||||
])
|
||||
|
||||
dnl CC_CHECK_CFLAG_APPEND(FLAG, [action-if-found], [action-if-not-found])
|
||||
dnl Check for CFLAG and appends them to CFLAGS if supported
|
||||
dnl Check for CFLAG and appends them to AM_CFLAGS if supported
|
||||
AC_DEFUN([CC_CHECK_CFLAG_APPEND], [
|
||||
AC_CACHE_CHECK([if $CC supports $1 flag],
|
||||
AS_TR_SH([cc_cv_cflags_$1]),
|
||||
@ -71,7 +72,9 @@ AC_DEFUN([CC_CHECK_CFLAG_APPEND], [
|
||||
)
|
||||
|
||||
AS_IF([eval test x$]AS_TR_SH([cc_cv_cflags_$1])[ = xyes],
|
||||
[CFLAGS="$CFLAGS $1"; DEBUG_CFLAGS="$DEBUG_CFLAGS $1"; $2], [$3])
|
||||
[AM_CFLAGS="$AM_CFLAGS $1"; DEBUG_CFLAGS="$DEBUG_CFLAGS $1"; $2], [$3])
|
||||
|
||||
AC_SUBST([AM_CFLAGS])
|
||||
])
|
||||
|
||||
dnl CC_CHECK_CFLAGS_APPEND([FLAG1 FLAG2], [action-if-found], [action-if-not])
|
||||
@ -101,6 +104,20 @@ AC_DEFUN([CC_CHECK_LDFLAGS], [
|
||||
[$2], [$3])
|
||||
])
|
||||
|
||||
dnl Check if flag is supported by both compiler and linker
|
||||
dnl If so, append it to AM_CFLAGS
|
||||
dnl CC_CHECK_FLAG_SUPPORTED_APPEND([FLAG])
|
||||
|
||||
AC_DEFUN([CC_CHECK_FLAG_SUPPORTED_APPEND], [
|
||||
CC_CHECK_CFLAGS([$1],
|
||||
[CC_CHECK_LDFLAGS([$1],
|
||||
[AM_CFLAGS="$AM_CFLAGS $1";
|
||||
DEBUG_CFLAGS="$DEBUG_CFLAGS $1";
|
||||
AC_SUBST([AM_CFLAGS])
|
||||
])
|
||||
])
|
||||
])
|
||||
|
||||
dnl define the LDFLAGS_NOUNDEFINED variable with the correct value for
|
||||
dnl the current linker to avoid undefined references in a shared object.
|
||||
AC_DEFUN([CC_NOUNDEFINED], [
|
||||
|
||||
7
m4/libuv-check-versions.m4
Normal file
7
m4/libuv-check-versions.m4
Normal file
@ -0,0 +1,7 @@
|
||||
|
||||
AC_PREREQ(2.71)
|
||||
AC_INIT([libuv-release-check], [0.0])
|
||||
AM_INIT_AUTOMAKE([1.16.5])
|
||||
LT_PREREQ(2.4.7)
|
||||
AC_OUTPUT
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
#ifdef _WIN32
|
||||
#include "win/internal.h"
|
||||
#include "win/handle-inl.h"
|
||||
#define uv__make_close_pending(h) uv_want_endgame((h)->loop, (h))
|
||||
#define uv__make_close_pending(h) uv__want_endgame((h)->loop, (h))
|
||||
#else
|
||||
#include "unix/internal.h"
|
||||
#endif
|
||||
@ -139,6 +139,9 @@ int uv_fs_poll_getpath(uv_fs_poll_t* handle, char* buffer, size_t* size) {
|
||||
struct poll_ctx* ctx;
|
||||
size_t required_len;
|
||||
|
||||
if (buffer == NULL || size == NULL || *size == 0)
|
||||
return UV_EINVAL;
|
||||
|
||||
if (!uv_is_active((uv_handle_t*)handle)) {
|
||||
*size = 0;
|
||||
return UV_EINVAL;
|
||||
|
||||
264
src/idna.c
264
src/idna.c
@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2011, 2018 Ben Noordhuis <info@bnoordhuis.nl>
|
||||
/* Copyright libuv contributors. All rights reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
@ -18,9 +18,55 @@
|
||||
*/
|
||||
|
||||
#include "uv.h"
|
||||
#include "uv-common.h"
|
||||
#include "idna.h"
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <limits.h> /* UINT_MAX */
|
||||
|
||||
|
||||
static int32_t uv__wtf8_decode1(const char** input) {
|
||||
uint32_t code_point;
|
||||
uint8_t b1;
|
||||
uint8_t b2;
|
||||
uint8_t b3;
|
||||
uint8_t b4;
|
||||
|
||||
b1 = **input;
|
||||
if (b1 <= 0x7F)
|
||||
return b1; /* ASCII code point */
|
||||
if (b1 < 0xC2)
|
||||
return -1; /* invalid: continuation byte */
|
||||
code_point = b1;
|
||||
|
||||
b2 = *++*input;
|
||||
if ((b2 & 0xC0) != 0x80)
|
||||
return -1; /* invalid: not a continuation byte */
|
||||
code_point = (code_point << 6) | (b2 & 0x3F);
|
||||
if (b1 <= 0xDF)
|
||||
return 0x7FF & code_point; /* two-byte character */
|
||||
|
||||
b3 = *++*input;
|
||||
if ((b3 & 0xC0) != 0x80)
|
||||
return -1; /* invalid: not a continuation byte */
|
||||
code_point = (code_point << 6) | (b3 & 0x3F);
|
||||
if (b1 <= 0xEF)
|
||||
return 0xFFFF & code_point; /* three-byte character */
|
||||
|
||||
b4 = *++*input;
|
||||
if ((b4 & 0xC0) != 0x80)
|
||||
return -1; /* invalid: not a continuation byte */
|
||||
code_point = (code_point << 6) | (b4 & 0x3F);
|
||||
if (b1 <= 0xF4) {
|
||||
code_point &= 0x1FFFFF;
|
||||
if (code_point <= 0x10FFFF)
|
||||
return code_point; /* four-byte character */
|
||||
}
|
||||
|
||||
/* code point too large */
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static unsigned uv__utf8_decode1_slow(const char** p,
|
||||
const char* pe,
|
||||
@ -88,6 +134,7 @@ static unsigned uv__utf8_decode1_slow(const char** p,
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
unsigned uv__utf8_decode1(const char** p, const char* pe) {
|
||||
unsigned a;
|
||||
|
||||
@ -101,6 +148,7 @@ unsigned uv__utf8_decode1(const char** p, const char* pe) {
|
||||
return uv__utf8_decode1_slow(p, pe, a);
|
||||
}
|
||||
|
||||
|
||||
static int uv__idna_toascii_label(const char* s, const char* se,
|
||||
char** d, char* de) {
|
||||
static const char alphabet[] = "abcdefghijklmnopqrstuvwxyz0123456789";
|
||||
@ -129,7 +177,7 @@ static int uv__idna_toascii_label(const char* s, const char* se,
|
||||
while (s < se) {
|
||||
c = uv__utf8_decode1(&s, se);
|
||||
|
||||
if (c == -1u)
|
||||
if (c == UINT_MAX)
|
||||
return UV_EINVAL;
|
||||
|
||||
if (c < 128)
|
||||
@ -151,7 +199,7 @@ static int uv__idna_toascii_label(const char* s, const char* se,
|
||||
s = ss;
|
||||
while (s < se) {
|
||||
c = uv__utf8_decode1(&s, se);
|
||||
assert(c != -1u);
|
||||
assert(c != UINT_MAX);
|
||||
|
||||
if (c > 127)
|
||||
continue;
|
||||
@ -182,7 +230,7 @@ static int uv__idna_toascii_label(const char* s, const char* se,
|
||||
|
||||
while (s < se) {
|
||||
c = uv__utf8_decode1(&s, se);
|
||||
assert(c != -1u);
|
||||
assert(c != UINT_MAX);
|
||||
|
||||
if (c >= n)
|
||||
if (c < m)
|
||||
@ -201,7 +249,7 @@ static int uv__idna_toascii_label(const char* s, const char* se,
|
||||
s = ss;
|
||||
while (s < se) {
|
||||
c = uv__utf8_decode1(&s, se);
|
||||
assert(c != -1u);
|
||||
assert(c != UINT_MAX);
|
||||
|
||||
if (c < n)
|
||||
if (++delta == 0)
|
||||
@ -266,13 +314,17 @@ static int uv__idna_toascii_label(const char* s, const char* se,
|
||||
return 0;
|
||||
}
|
||||
|
||||
long uv__idna_toascii(const char* s, const char* se, char* d, char* de) {
|
||||
|
||||
ssize_t uv__idna_toascii(const char* s, const char* se, char* d, char* de) {
|
||||
const char* si;
|
||||
const char* st;
|
||||
unsigned c;
|
||||
char* ds;
|
||||
int rc;
|
||||
|
||||
if (s == se)
|
||||
return UV_EINVAL;
|
||||
|
||||
ds = d;
|
||||
|
||||
si = s;
|
||||
@ -280,7 +332,7 @@ long uv__idna_toascii(const char* s, const char* se, char* d, char* de) {
|
||||
st = si;
|
||||
c = uv__utf8_decode1(&si, se);
|
||||
|
||||
if (c == -1u)
|
||||
if (c == UINT_MAX)
|
||||
return UV_EINVAL;
|
||||
|
||||
if (c != '.')
|
||||
@ -307,8 +359,202 @@ long uv__idna_toascii(const char* s, const char* se, char* d, char* de) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (d < de)
|
||||
*d++ = '\0';
|
||||
if (d >= de)
|
||||
return UV_EINVAL;
|
||||
|
||||
*d++ = '\0';
|
||||
return d - ds; /* Number of bytes written. */
|
||||
}
|
||||
|
||||
|
||||
ssize_t uv_wtf8_length_as_utf16(const char* source_ptr) {
|
||||
size_t w_target_len = 0;
|
||||
int32_t code_point;
|
||||
|
||||
do {
|
||||
code_point = uv__wtf8_decode1(&source_ptr);
|
||||
if (code_point < 0)
|
||||
return -1;
|
||||
if (code_point > 0xFFFF)
|
||||
w_target_len++;
|
||||
w_target_len++;
|
||||
} while (*source_ptr++);
|
||||
|
||||
return w_target_len;
|
||||
}
|
||||
|
||||
|
||||
void uv_wtf8_to_utf16(const char* source_ptr,
|
||||
uint16_t* w_target,
|
||||
size_t w_target_len) {
|
||||
int32_t code_point;
|
||||
|
||||
do {
|
||||
code_point = uv__wtf8_decode1(&source_ptr);
|
||||
/* uv_wtf8_length_as_utf16 should have been called and checked first. */
|
||||
assert(code_point >= 0);
|
||||
if (code_point > 0xFFFF) {
|
||||
assert(code_point < 0x10FFFF);
|
||||
*w_target++ = (((code_point - 0x10000) >> 10) + 0xD800);
|
||||
*w_target++ = ((code_point - 0x10000) & 0x3FF) + 0xDC00;
|
||||
w_target_len -= 2;
|
||||
} else {
|
||||
*w_target++ = code_point;
|
||||
w_target_len -= 1;
|
||||
}
|
||||
} while (*source_ptr++);
|
||||
|
||||
(void)w_target_len;
|
||||
assert(w_target_len == 0);
|
||||
}
|
||||
|
||||
|
||||
static int32_t uv__get_surrogate_value(const uint16_t* w_source_ptr,
|
||||
ssize_t w_source_len) {
|
||||
uint16_t u;
|
||||
uint16_t next;
|
||||
|
||||
u = w_source_ptr[0];
|
||||
if (u >= 0xD800 && u <= 0xDBFF && w_source_len != 1) {
|
||||
next = w_source_ptr[1];
|
||||
if (next >= 0xDC00 && next <= 0xDFFF)
|
||||
return 0x10000 + ((u - 0xD800) << 10) + (next - 0xDC00);
|
||||
}
|
||||
return u;
|
||||
}
|
||||
|
||||
|
||||
size_t uv_utf16_length_as_wtf8(const uint16_t* w_source_ptr,
|
||||
ssize_t w_source_len) {
|
||||
size_t target_len;
|
||||
int32_t code_point;
|
||||
|
||||
target_len = 0;
|
||||
while (w_source_len) {
|
||||
code_point = uv__get_surrogate_value(w_source_ptr, w_source_len);
|
||||
/* Can be invalid UTF-8 but must be valid WTF-8. */
|
||||
assert(code_point >= 0);
|
||||
if (w_source_len < 0 && code_point == 0)
|
||||
break;
|
||||
if (code_point < 0x80)
|
||||
target_len += 1;
|
||||
else if (code_point < 0x800)
|
||||
target_len += 2;
|
||||
else if (code_point < 0x10000)
|
||||
target_len += 3;
|
||||
else {
|
||||
target_len += 4;
|
||||
w_source_ptr++;
|
||||
if (w_source_len > 0)
|
||||
w_source_len--;
|
||||
}
|
||||
w_source_ptr++;
|
||||
if (w_source_len > 0)
|
||||
w_source_len--;
|
||||
}
|
||||
|
||||
return target_len;
|
||||
}
|
||||
|
||||
|
||||
int uv_utf16_to_wtf8(const uint16_t* w_source_ptr,
|
||||
ssize_t w_source_len,
|
||||
char** target_ptr,
|
||||
size_t* target_len_ptr) {
|
||||
size_t target_len;
|
||||
char* target;
|
||||
char* target_end;
|
||||
int32_t code_point;
|
||||
|
||||
/* If *target_ptr is provided, then *target_len_ptr must be its length
|
||||
* (excluding space for NUL), otherwise we will compute the target_len_ptr
|
||||
* length and may return a new allocation in *target_ptr if target_ptr is
|
||||
* provided. */
|
||||
if (target_ptr == NULL || *target_ptr == NULL) {
|
||||
target_len = uv_utf16_length_as_wtf8(w_source_ptr, w_source_len);
|
||||
if (target_len_ptr != NULL)
|
||||
*target_len_ptr = target_len;
|
||||
} else {
|
||||
target_len = *target_len_ptr;
|
||||
}
|
||||
|
||||
if (target_ptr == NULL)
|
||||
return 0;
|
||||
|
||||
if (*target_ptr == NULL) {
|
||||
target = uv__malloc(target_len + 1);
|
||||
if (target == NULL) {
|
||||
return UV_ENOMEM;
|
||||
}
|
||||
*target_ptr = target;
|
||||
} else {
|
||||
target = *target_ptr;
|
||||
}
|
||||
|
||||
target_end = target + target_len;
|
||||
|
||||
while (target != target_end && w_source_len) {
|
||||
code_point = uv__get_surrogate_value(w_source_ptr, w_source_len);
|
||||
/* Can be invalid UTF-8 but must be valid WTF-8. */
|
||||
assert(code_point >= 0);
|
||||
if (w_source_len < 0 && code_point == 0) {
|
||||
w_source_len = 0;
|
||||
break;
|
||||
}
|
||||
if (code_point < 0x80) {
|
||||
*target++ = code_point;
|
||||
} else if (code_point < 0x800) {
|
||||
*target++ = 0xC0 | (code_point >> 6);
|
||||
if (target == target_end)
|
||||
break;
|
||||
*target++ = 0x80 | (code_point & 0x3F);
|
||||
} else if (code_point < 0x10000) {
|
||||
*target++ = 0xE0 | (code_point >> 12);
|
||||
if (target == target_end)
|
||||
break;
|
||||
*target++ = 0x80 | ((code_point >> 6) & 0x3F);
|
||||
if (target == target_end)
|
||||
break;
|
||||
*target++ = 0x80 | (code_point & 0x3F);
|
||||
} else {
|
||||
*target++ = 0xF0 | (code_point >> 18);
|
||||
if (target == target_end)
|
||||
break;
|
||||
*target++ = 0x80 | ((code_point >> 12) & 0x3F);
|
||||
if (target == target_end)
|
||||
break;
|
||||
*target++ = 0x80 | ((code_point >> 6) & 0x3F);
|
||||
if (target == target_end)
|
||||
break;
|
||||
*target++ = 0x80 | (code_point & 0x3F);
|
||||
/* uv__get_surrogate_value consumed 2 input characters */
|
||||
w_source_ptr++;
|
||||
if (w_source_len > 0)
|
||||
w_source_len--;
|
||||
}
|
||||
target_len = target - *target_ptr;
|
||||
w_source_ptr++;
|
||||
if (w_source_len > 0)
|
||||
w_source_len--;
|
||||
}
|
||||
|
||||
if (target != target_end && target_len_ptr != NULL)
|
||||
/* Did not fill all of the provided buffer, so update the target_len_ptr
|
||||
* output with the space used. */
|
||||
*target_len_ptr = target - *target_ptr;
|
||||
|
||||
/* Check if input fit into target exactly. */
|
||||
if (w_source_len < 0 && target == target_end && w_source_ptr[0] == 0)
|
||||
w_source_len = 0;
|
||||
|
||||
*target++ = '\0';
|
||||
|
||||
/* Characters remained after filling the buffer, compute the remaining length now. */
|
||||
if (w_source_len) {
|
||||
if (target_len_ptr != NULL)
|
||||
*target_len_ptr = target_len + uv_utf16_length_as_wtf8(w_source_ptr, w_source_len);
|
||||
return UV_ENOBUFS;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2011, 2018 Ben Noordhuis <info@bnoordhuis.nl>
|
||||
/* Copyright libuv contributors. All rights reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
@ -26,6 +26,6 @@ unsigned uv__utf8_decode1(const char** p, const char* pe);
|
||||
* is the number of bytes written to |d|, including the trailing nul byte.
|
||||
* A return value < 0 is a libuv error code. |s| and |d| can not overlap.
|
||||
*/
|
||||
long uv__idna_toascii(const char* s, const char* se, char* d, char* de);
|
||||
ssize_t uv__idna_toascii(const char* s, const char* se, char* d, char* de);
|
||||
|
||||
#endif /* UV_SRC_IDNA_H_ */
|
||||
|
||||
@ -17,12 +17,7 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1600
|
||||
# include "uv/stdint-msvc2008.h"
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#include "uv.h"
|
||||
#include "uv-common.h"
|
||||
@ -135,7 +130,7 @@ static int inet_ntop6(const unsigned char *src, char *dst, size_t size) {
|
||||
tp += strlen(tp);
|
||||
break;
|
||||
}
|
||||
tp += sprintf(tp, "%x", words[i]);
|
||||
tp += snprintf(tp, sizeof tmp - (tp - tmp), "%x", words[i]);
|
||||
}
|
||||
/* Was it a trailing run of 0x00's? */
|
||||
if (best.base != -1 && (best.base + best.len) == ARRAY_SIZE(words))
|
||||
|
||||
132
src/queue.h
132
src/queue.h
@ -18,91 +18,73 @@
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
typedef void *QUEUE[2];
|
||||
#define uv__queue_data(pointer, type, field) \
|
||||
((type*) ((char*) (pointer) - offsetof(type, field)))
|
||||
|
||||
/* Private macros. */
|
||||
#define QUEUE_NEXT(q) (*(QUEUE **) &((*(q))[0]))
|
||||
#define QUEUE_PREV(q) (*(QUEUE **) &((*(q))[1]))
|
||||
#define QUEUE_PREV_NEXT(q) (QUEUE_NEXT(QUEUE_PREV(q)))
|
||||
#define QUEUE_NEXT_PREV(q) (QUEUE_PREV(QUEUE_NEXT(q)))
|
||||
#define uv__queue_foreach(q, h) \
|
||||
for ((q) = (h)->next; (q) != (h); (q) = (q)->next)
|
||||
|
||||
/* Public macros. */
|
||||
#define QUEUE_DATA(ptr, type, field) \
|
||||
((type *) ((char *) (ptr) - offsetof(type, field)))
|
||||
static inline void uv__queue_init(struct uv__queue* q) {
|
||||
q->next = q;
|
||||
q->prev = q;
|
||||
}
|
||||
|
||||
/* Important note: mutating the list while QUEUE_FOREACH is
|
||||
* iterating over its elements results in undefined behavior.
|
||||
*/
|
||||
#define QUEUE_FOREACH(q, h) \
|
||||
for ((q) = QUEUE_NEXT(h); (q) != (h); (q) = QUEUE_NEXT(q))
|
||||
static inline int uv__queue_empty(const struct uv__queue* q) {
|
||||
return q == q->next;
|
||||
}
|
||||
|
||||
#define QUEUE_EMPTY(q) \
|
||||
((const QUEUE *) (q) == (const QUEUE *) QUEUE_NEXT(q))
|
||||
static inline struct uv__queue* uv__queue_head(const struct uv__queue* q) {
|
||||
return q->next;
|
||||
}
|
||||
|
||||
#define QUEUE_HEAD(q) \
|
||||
(QUEUE_NEXT(q))
|
||||
static inline struct uv__queue* uv__queue_next(const struct uv__queue* q) {
|
||||
return q->next;
|
||||
}
|
||||
|
||||
#define QUEUE_INIT(q) \
|
||||
do { \
|
||||
QUEUE_NEXT(q) = (q); \
|
||||
QUEUE_PREV(q) = (q); \
|
||||
} \
|
||||
while (0)
|
||||
static inline void uv__queue_add(struct uv__queue* h, struct uv__queue* n) {
|
||||
h->prev->next = n->next;
|
||||
n->next->prev = h->prev;
|
||||
h->prev = n->prev;
|
||||
h->prev->next = h;
|
||||
}
|
||||
|
||||
#define QUEUE_ADD(h, n) \
|
||||
do { \
|
||||
QUEUE_PREV_NEXT(h) = QUEUE_NEXT(n); \
|
||||
QUEUE_NEXT_PREV(n) = QUEUE_PREV(h); \
|
||||
QUEUE_PREV(h) = QUEUE_PREV(n); \
|
||||
QUEUE_PREV_NEXT(h) = (h); \
|
||||
} \
|
||||
while (0)
|
||||
static inline void uv__queue_split(struct uv__queue* h,
|
||||
struct uv__queue* q,
|
||||
struct uv__queue* n) {
|
||||
n->prev = h->prev;
|
||||
n->prev->next = n;
|
||||
n->next = q;
|
||||
h->prev = q->prev;
|
||||
h->prev->next = h;
|
||||
q->prev = n;
|
||||
}
|
||||
|
||||
#define QUEUE_SPLIT(h, q, n) \
|
||||
do { \
|
||||
QUEUE_PREV(n) = QUEUE_PREV(h); \
|
||||
QUEUE_PREV_NEXT(n) = (n); \
|
||||
QUEUE_NEXT(n) = (q); \
|
||||
QUEUE_PREV(h) = QUEUE_PREV(q); \
|
||||
QUEUE_PREV_NEXT(h) = (h); \
|
||||
QUEUE_PREV(q) = (n); \
|
||||
} \
|
||||
while (0)
|
||||
static inline void uv__queue_move(struct uv__queue* h, struct uv__queue* n) {
|
||||
if (uv__queue_empty(h))
|
||||
uv__queue_init(n);
|
||||
else
|
||||
uv__queue_split(h, h->next, n);
|
||||
}
|
||||
|
||||
#define QUEUE_MOVE(h, n) \
|
||||
do { \
|
||||
if (QUEUE_EMPTY(h)) \
|
||||
QUEUE_INIT(n); \
|
||||
else { \
|
||||
QUEUE* q = QUEUE_HEAD(h); \
|
||||
QUEUE_SPLIT(h, q, n); \
|
||||
} \
|
||||
} \
|
||||
while (0)
|
||||
static inline void uv__queue_insert_head(struct uv__queue* h,
|
||||
struct uv__queue* q) {
|
||||
q->next = h->next;
|
||||
q->prev = h;
|
||||
q->next->prev = q;
|
||||
h->next = q;
|
||||
}
|
||||
|
||||
#define QUEUE_INSERT_HEAD(h, q) \
|
||||
do { \
|
||||
QUEUE_NEXT(q) = QUEUE_NEXT(h); \
|
||||
QUEUE_PREV(q) = (h); \
|
||||
QUEUE_NEXT_PREV(q) = (q); \
|
||||
QUEUE_NEXT(h) = (q); \
|
||||
} \
|
||||
while (0)
|
||||
static inline void uv__queue_insert_tail(struct uv__queue* h,
|
||||
struct uv__queue* q) {
|
||||
q->next = h;
|
||||
q->prev = h->prev;
|
||||
q->prev->next = q;
|
||||
h->prev = q;
|
||||
}
|
||||
|
||||
#define QUEUE_INSERT_TAIL(h, q) \
|
||||
do { \
|
||||
QUEUE_NEXT(q) = (h); \
|
||||
QUEUE_PREV(q) = QUEUE_PREV(h); \
|
||||
QUEUE_PREV_NEXT(q) = (q); \
|
||||
QUEUE_PREV(h) = (q); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
#define QUEUE_REMOVE(q) \
|
||||
do { \
|
||||
QUEUE_PREV_NEXT(q) = QUEUE_NEXT(q); \
|
||||
QUEUE_NEXT_PREV(q) = QUEUE_PREV(q); \
|
||||
} \
|
||||
while (0)
|
||||
static inline void uv__queue_remove(struct uv__queue* q) {
|
||||
q->prev->next = q->next;
|
||||
q->next->prev = q->prev;
|
||||
}
|
||||
|
||||
#endif /* QUEUE_H_ */
|
||||
|
||||
@ -82,7 +82,7 @@ static void uv__random_done(struct uv__work* w, int status) {
|
||||
uv_random_t* req;
|
||||
|
||||
req = container_of(w, uv_random_t, work_req);
|
||||
uv__req_unregister(req->loop, req);
|
||||
uv__req_unregister(req->loop);
|
||||
|
||||
if (status == 0)
|
||||
status = req->status;
|
||||
|
||||
@ -28,7 +28,7 @@
|
||||
*/
|
||||
#include "uv.h"
|
||||
|
||||
/* Copies up to |n-1| bytes from |d| to |s| and always zero-terminates
|
||||
/* Copies up to |n-1| bytes from |s| to |d| and always zero-terminates
|
||||
* the result, except when |n==0|. Returns the number of bytes copied
|
||||
* or UV_E2BIG if |d| is too small.
|
||||
*
|
||||
|
||||
52
src/strtok.c
Normal file
52
src/strtok.c
Normal file
@ -0,0 +1,52 @@
|
||||
/* Copyright libuv project contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "strtok.h"
|
||||
|
||||
char* uv__strtok(char* str, const char* sep, char** itr) {
|
||||
const char* sep_itr;
|
||||
char* tmp;
|
||||
char* start;
|
||||
|
||||
if (str == NULL)
|
||||
start = tmp = *itr;
|
||||
else
|
||||
start = tmp = str;
|
||||
|
||||
if (tmp == NULL)
|
||||
return NULL;
|
||||
|
||||
while (*tmp != '\0') {
|
||||
sep_itr = sep;
|
||||
while (*sep_itr != '\0') {
|
||||
if (*tmp == *sep_itr) {
|
||||
*itr = tmp + 1;
|
||||
*tmp = '\0';
|
||||
return start;
|
||||
}
|
||||
sep_itr++;
|
||||
}
|
||||
tmp++;
|
||||
}
|
||||
*itr = NULL;
|
||||
return start;
|
||||
}
|
||||
27
src/strtok.h
Normal file
27
src/strtok.h
Normal file
@ -0,0 +1,27 @@
|
||||
/* Copyright libuv project contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef UV_STRTOK_H_
|
||||
#define UV_STRTOK_H_
|
||||
|
||||
char* uv__strtok(char* str, const char* sep, char** itr);
|
||||
|
||||
#endif /* UV_STRTOK_H_ */
|
||||
175
src/thread-common.c
Normal file
175
src/thread-common.c
Normal file
@ -0,0 +1,175 @@
|
||||
/* Copyright libuv project contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "uv.h"
|
||||
#include "uv-common.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#ifndef _WIN32
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#if defined(PTHREAD_BARRIER_SERIAL_THREAD)
|
||||
STATIC_ASSERT(sizeof(uv_barrier_t) == sizeof(pthread_barrier_t));
|
||||
#endif
|
||||
|
||||
/* Note: guard clauses should match uv_barrier_t's in include/uv/unix.h. */
|
||||
#if defined(_AIX) || \
|
||||
defined(__OpenBSD__) || \
|
||||
!defined(PTHREAD_BARRIER_SERIAL_THREAD)
|
||||
int uv_barrier_init(uv_barrier_t* barrier, unsigned int count) {
|
||||
int rc;
|
||||
#ifdef _WIN32
|
||||
uv_barrier_t* b;
|
||||
b = barrier;
|
||||
|
||||
if (barrier == NULL || count == 0)
|
||||
return UV_EINVAL;
|
||||
#else
|
||||
struct _uv_barrier* b;
|
||||
|
||||
if (barrier == NULL || count == 0)
|
||||
return UV_EINVAL;
|
||||
|
||||
b = uv__malloc(sizeof(*b));
|
||||
if (b == NULL)
|
||||
return UV_ENOMEM;
|
||||
#endif
|
||||
|
||||
b->in = 0;
|
||||
b->out = 0;
|
||||
b->threshold = count;
|
||||
|
||||
rc = uv_mutex_init(&b->mutex);
|
||||
if (rc != 0)
|
||||
goto error2;
|
||||
|
||||
/* TODO(vjnash): remove these uv_cond_t casts in v2. */
|
||||
rc = uv_cond_init((uv_cond_t*) &b->cond);
|
||||
if (rc != 0)
|
||||
goto error;
|
||||
|
||||
#ifndef _WIN32
|
||||
barrier->b = b;
|
||||
#endif
|
||||
return 0;
|
||||
|
||||
error:
|
||||
uv_mutex_destroy(&b->mutex);
|
||||
error2:
|
||||
#ifndef _WIN32
|
||||
uv__free(b);
|
||||
#endif
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
int uv_barrier_wait(uv_barrier_t* barrier) {
|
||||
int last;
|
||||
#ifdef _WIN32
|
||||
uv_barrier_t* b;
|
||||
b = barrier;
|
||||
#else
|
||||
struct _uv_barrier* b;
|
||||
|
||||
if (barrier == NULL || barrier->b == NULL)
|
||||
return UV_EINVAL;
|
||||
|
||||
b = barrier->b;
|
||||
#endif
|
||||
|
||||
uv_mutex_lock(&b->mutex);
|
||||
|
||||
while (b->out != 0)
|
||||
uv_cond_wait((uv_cond_t*) &b->cond, &b->mutex);
|
||||
|
||||
if (++b->in == b->threshold) {
|
||||
b->in = 0;
|
||||
b->out = b->threshold;
|
||||
uv_cond_broadcast((uv_cond_t*) &b->cond);
|
||||
} else {
|
||||
do
|
||||
uv_cond_wait((uv_cond_t*) &b->cond, &b->mutex);
|
||||
while (b->in != 0);
|
||||
}
|
||||
|
||||
last = (--b->out == 0);
|
||||
if (last)
|
||||
uv_cond_broadcast((uv_cond_t*) &b->cond);
|
||||
|
||||
uv_mutex_unlock(&b->mutex);
|
||||
return last;
|
||||
}
|
||||
|
||||
|
||||
void uv_barrier_destroy(uv_barrier_t* barrier) {
|
||||
#ifdef _WIN32
|
||||
uv_barrier_t* b;
|
||||
b = barrier;
|
||||
#else
|
||||
struct _uv_barrier* b;
|
||||
b = barrier->b;
|
||||
#endif
|
||||
|
||||
uv_mutex_lock(&b->mutex);
|
||||
|
||||
assert(b->in == 0);
|
||||
while (b->out != 0)
|
||||
uv_cond_wait((uv_cond_t*) &b->cond, &b->mutex);
|
||||
|
||||
if (b->in != 0)
|
||||
abort();
|
||||
|
||||
uv_mutex_unlock(&b->mutex);
|
||||
uv_mutex_destroy(&b->mutex);
|
||||
uv_cond_destroy((uv_cond_t*) &b->cond);
|
||||
|
||||
#ifndef _WIN32
|
||||
uv__free(barrier->b);
|
||||
barrier->b = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int uv_barrier_init(uv_barrier_t* barrier, unsigned int count) {
|
||||
return UV__ERR(pthread_barrier_init(barrier, NULL, count));
|
||||
}
|
||||
|
||||
|
||||
int uv_barrier_wait(uv_barrier_t* barrier) {
|
||||
int rc;
|
||||
|
||||
rc = pthread_barrier_wait(barrier);
|
||||
if (rc != 0)
|
||||
if (rc != PTHREAD_BARRIER_SERIAL_THREAD)
|
||||
abort();
|
||||
|
||||
return rc == PTHREAD_BARRIER_SERIAL_THREAD;
|
||||
}
|
||||
|
||||
|
||||
void uv_barrier_destroy(uv_barrier_t* barrier) {
|
||||
if (pthread_barrier_destroy(barrier))
|
||||
abort();
|
||||
}
|
||||
|
||||
#endif
|
||||
102
src/threadpool.c
102
src/threadpool.c
@ -37,10 +37,10 @@ static unsigned int slow_io_work_running;
|
||||
static unsigned int nthreads;
|
||||
static uv_thread_t* threads;
|
||||
static uv_thread_t default_threads[4];
|
||||
static QUEUE exit_message;
|
||||
static QUEUE wq;
|
||||
static QUEUE run_slow_work_message;
|
||||
static QUEUE slow_io_pending_wq;
|
||||
static struct uv__queue exit_message;
|
||||
static struct uv__queue wq;
|
||||
static struct uv__queue run_slow_work_message;
|
||||
static struct uv__queue slow_io_pending_wq;
|
||||
|
||||
static unsigned int slow_work_thread_threshold(void) {
|
||||
return (nthreads + 1) / 2;
|
||||
@ -56,9 +56,10 @@ static void uv__cancelled(struct uv__work* w) {
|
||||
*/
|
||||
static void worker(void* arg) {
|
||||
struct uv__work* w;
|
||||
QUEUE* q;
|
||||
struct uv__queue* q;
|
||||
int is_slow_work;
|
||||
|
||||
uv_thread_setname("libuv-worker");
|
||||
uv_sem_post((uv_sem_t*) arg);
|
||||
arg = NULL;
|
||||
|
||||
@ -68,49 +69,49 @@ static void worker(void* arg) {
|
||||
|
||||
/* Keep waiting while either no work is present or only slow I/O
|
||||
and we're at the threshold for that. */
|
||||
while (QUEUE_EMPTY(&wq) ||
|
||||
(QUEUE_HEAD(&wq) == &run_slow_work_message &&
|
||||
QUEUE_NEXT(&run_slow_work_message) == &wq &&
|
||||
while (uv__queue_empty(&wq) ||
|
||||
(uv__queue_head(&wq) == &run_slow_work_message &&
|
||||
uv__queue_next(&run_slow_work_message) == &wq &&
|
||||
slow_io_work_running >= slow_work_thread_threshold())) {
|
||||
idle_threads += 1;
|
||||
uv_cond_wait(&cond, &mutex);
|
||||
idle_threads -= 1;
|
||||
}
|
||||
|
||||
q = QUEUE_HEAD(&wq);
|
||||
q = uv__queue_head(&wq);
|
||||
if (q == &exit_message) {
|
||||
uv_cond_signal(&cond);
|
||||
uv_mutex_unlock(&mutex);
|
||||
break;
|
||||
}
|
||||
|
||||
QUEUE_REMOVE(q);
|
||||
QUEUE_INIT(q); /* Signal uv_cancel() that the work req is executing. */
|
||||
uv__queue_remove(q);
|
||||
uv__queue_init(q); /* Signal uv_cancel() that the work req is executing. */
|
||||
|
||||
is_slow_work = 0;
|
||||
if (q == &run_slow_work_message) {
|
||||
/* If we're at the slow I/O threshold, re-schedule until after all
|
||||
other work in the queue is done. */
|
||||
if (slow_io_work_running >= slow_work_thread_threshold()) {
|
||||
QUEUE_INSERT_TAIL(&wq, q);
|
||||
uv__queue_insert_tail(&wq, q);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* If we encountered a request to run slow I/O work but there is none
|
||||
to run, that means it's cancelled => Start over. */
|
||||
if (QUEUE_EMPTY(&slow_io_pending_wq))
|
||||
if (uv__queue_empty(&slow_io_pending_wq))
|
||||
continue;
|
||||
|
||||
is_slow_work = 1;
|
||||
slow_io_work_running++;
|
||||
|
||||
q = QUEUE_HEAD(&slow_io_pending_wq);
|
||||
QUEUE_REMOVE(q);
|
||||
QUEUE_INIT(q);
|
||||
q = uv__queue_head(&slow_io_pending_wq);
|
||||
uv__queue_remove(q);
|
||||
uv__queue_init(q);
|
||||
|
||||
/* If there is more slow I/O work, schedule it to be run as well. */
|
||||
if (!QUEUE_EMPTY(&slow_io_pending_wq)) {
|
||||
QUEUE_INSERT_TAIL(&wq, &run_slow_work_message);
|
||||
if (!uv__queue_empty(&slow_io_pending_wq)) {
|
||||
uv__queue_insert_tail(&wq, &run_slow_work_message);
|
||||
if (idle_threads > 0)
|
||||
uv_cond_signal(&cond);
|
||||
}
|
||||
@ -118,13 +119,13 @@ static void worker(void* arg) {
|
||||
|
||||
uv_mutex_unlock(&mutex);
|
||||
|
||||
w = QUEUE_DATA(q, struct uv__work, wq);
|
||||
w = uv__queue_data(q, struct uv__work, wq);
|
||||
w->work(w);
|
||||
|
||||
uv_mutex_lock(&w->loop->wq_mutex);
|
||||
w->work = NULL; /* Signal uv_cancel() that the work req is done
|
||||
executing. */
|
||||
QUEUE_INSERT_TAIL(&w->loop->wq, &w->wq);
|
||||
uv__queue_insert_tail(&w->loop->wq, &w->wq);
|
||||
uv_async_send(&w->loop->wq_async);
|
||||
uv_mutex_unlock(&w->loop->wq_mutex);
|
||||
|
||||
@ -139,12 +140,12 @@ static void worker(void* arg) {
|
||||
}
|
||||
|
||||
|
||||
static void post(QUEUE* q, enum uv__work_kind kind) {
|
||||
static void post(struct uv__queue* q, enum uv__work_kind kind) {
|
||||
uv_mutex_lock(&mutex);
|
||||
if (kind == UV__WORK_SLOW_IO) {
|
||||
/* Insert into a separate queue. */
|
||||
QUEUE_INSERT_TAIL(&slow_io_pending_wq, q);
|
||||
if (!QUEUE_EMPTY(&run_slow_work_message)) {
|
||||
uv__queue_insert_tail(&slow_io_pending_wq, q);
|
||||
if (!uv__queue_empty(&run_slow_work_message)) {
|
||||
/* Running slow I/O tasks is already scheduled => Nothing to do here.
|
||||
The worker that runs said other task will schedule this one as well. */
|
||||
uv_mutex_unlock(&mutex);
|
||||
@ -153,7 +154,7 @@ static void post(QUEUE* q, enum uv__work_kind kind) {
|
||||
q = &run_slow_work_message;
|
||||
}
|
||||
|
||||
QUEUE_INSERT_TAIL(&wq, q);
|
||||
uv__queue_insert_tail(&wq, q);
|
||||
if (idle_threads > 0)
|
||||
uv_cond_signal(&cond);
|
||||
uv_mutex_unlock(&mutex);
|
||||
@ -191,6 +192,7 @@ void uv__threadpool_cleanup(void) {
|
||||
|
||||
|
||||
static void init_threads(void) {
|
||||
uv_thread_options_t config;
|
||||
unsigned int i;
|
||||
const char* val;
|
||||
uv_sem_t sem;
|
||||
@ -219,15 +221,18 @@ static void init_threads(void) {
|
||||
if (uv_mutex_init(&mutex))
|
||||
abort();
|
||||
|
||||
QUEUE_INIT(&wq);
|
||||
QUEUE_INIT(&slow_io_pending_wq);
|
||||
QUEUE_INIT(&run_slow_work_message);
|
||||
uv__queue_init(&wq);
|
||||
uv__queue_init(&slow_io_pending_wq);
|
||||
uv__queue_init(&run_slow_work_message);
|
||||
|
||||
if (uv_sem_init(&sem, 0))
|
||||
abort();
|
||||
|
||||
config.flags = UV_THREAD_HAS_STACK_SIZE;
|
||||
config.stack_size = 8u << 20; /* 8 MB */
|
||||
|
||||
for (i = 0; i < nthreads; i++)
|
||||
if (uv_thread_create(threads + i, worker, &sem))
|
||||
if (uv_thread_create_ex(threads + i, &config, worker, &sem))
|
||||
abort();
|
||||
|
||||
for (i = 0; i < nthreads; i++)
|
||||
@ -271,15 +276,19 @@ void uv__work_submit(uv_loop_t* loop,
|
||||
}
|
||||
|
||||
|
||||
/* TODO(bnoordhuis) teach libuv how to cancel file operations
|
||||
* that go through io_uring instead of the thread pool.
|
||||
*/
|
||||
static int uv__work_cancel(uv_loop_t* loop, uv_req_t* req, struct uv__work* w) {
|
||||
int cancelled;
|
||||
|
||||
uv_once(&once, init_once); /* Ensure |mutex| is initialized. */
|
||||
uv_mutex_lock(&mutex);
|
||||
uv_mutex_lock(&w->loop->wq_mutex);
|
||||
|
||||
cancelled = !QUEUE_EMPTY(&w->wq) && w->work != NULL;
|
||||
cancelled = !uv__queue_empty(&w->wq) && w->work != NULL;
|
||||
if (cancelled)
|
||||
QUEUE_REMOVE(&w->wq);
|
||||
uv__queue_remove(&w->wq);
|
||||
|
||||
uv_mutex_unlock(&w->loop->wq_mutex);
|
||||
uv_mutex_unlock(&mutex);
|
||||
@ -289,7 +298,7 @@ static int uv__work_cancel(uv_loop_t* loop, uv_req_t* req, struct uv__work* w) {
|
||||
|
||||
w->work = uv__cancelled;
|
||||
uv_mutex_lock(&loop->wq_mutex);
|
||||
QUEUE_INSERT_TAIL(&loop->wq, &w->wq);
|
||||
uv__queue_insert_tail(&loop->wq, &w->wq);
|
||||
uv_async_send(&loop->wq_async);
|
||||
uv_mutex_unlock(&loop->wq_mutex);
|
||||
|
||||
@ -300,22 +309,39 @@ static int uv__work_cancel(uv_loop_t* loop, uv_req_t* req, struct uv__work* w) {
|
||||
void uv__work_done(uv_async_t* handle) {
|
||||
struct uv__work* w;
|
||||
uv_loop_t* loop;
|
||||
QUEUE* q;
|
||||
QUEUE wq;
|
||||
struct uv__queue* q;
|
||||
struct uv__queue wq;
|
||||
int err;
|
||||
int nevents;
|
||||
|
||||
loop = container_of(handle, uv_loop_t, wq_async);
|
||||
uv_mutex_lock(&loop->wq_mutex);
|
||||
QUEUE_MOVE(&loop->wq, &wq);
|
||||
uv__queue_move(&loop->wq, &wq);
|
||||
uv_mutex_unlock(&loop->wq_mutex);
|
||||
|
||||
while (!QUEUE_EMPTY(&wq)) {
|
||||
q = QUEUE_HEAD(&wq);
|
||||
QUEUE_REMOVE(q);
|
||||
nevents = 0;
|
||||
|
||||
while (!uv__queue_empty(&wq)) {
|
||||
q = uv__queue_head(&wq);
|
||||
uv__queue_remove(q);
|
||||
|
||||
w = container_of(q, struct uv__work, wq);
|
||||
err = (w->work == uv__cancelled) ? UV_ECANCELED : 0;
|
||||
w->done(w, err);
|
||||
nevents++;
|
||||
}
|
||||
|
||||
/* This check accomplishes 2 things:
|
||||
* 1. Even if the queue was empty, the call to uv__work_done() should count
|
||||
* as an event. Which will have been added by the event loop when
|
||||
* calling this callback.
|
||||
* 2. Prevents accidental wrap around in case nevents == 0 events == 0.
|
||||
*/
|
||||
if (nevents > 1) {
|
||||
/* Subtract 1 to counter the call to uv__work_done(). */
|
||||
uv__metrics_inc_events(loop, nevents - 1);
|
||||
if (uv__get_internal_fields(loop)->current_timeout == 0)
|
||||
uv__metrics_inc_events_waiting(loop, nevents - 1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -331,7 +357,7 @@ static void uv__queue_done(struct uv__work* w, int err) {
|
||||
uv_work_t* req;
|
||||
|
||||
req = container_of(w, uv_work_t, work_req);
|
||||
uv__req_unregister(req->loop, req);
|
||||
uv__req_unregister(req->loop);
|
||||
|
||||
if (req->after_work_cb == NULL)
|
||||
return;
|
||||
|
||||
35
src/timer.c
35
src/timer.c
@ -40,8 +40,8 @@ static int timer_less_than(const struct heap_node* ha,
|
||||
const uv_timer_t* a;
|
||||
const uv_timer_t* b;
|
||||
|
||||
a = container_of(ha, uv_timer_t, heap_node);
|
||||
b = container_of(hb, uv_timer_t, heap_node);
|
||||
a = container_of(ha, uv_timer_t, node.heap);
|
||||
b = container_of(hb, uv_timer_t, node.heap);
|
||||
|
||||
if (a->timeout < b->timeout)
|
||||
return 1;
|
||||
@ -60,6 +60,7 @@ int uv_timer_init(uv_loop_t* loop, uv_timer_t* handle) {
|
||||
handle->timer_cb = NULL;
|
||||
handle->timeout = 0;
|
||||
handle->repeat = 0;
|
||||
uv__queue_init(&handle->node.queue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -73,7 +74,6 @@ int uv_timer_start(uv_timer_t* handle,
|
||||
if (uv__is_closing(handle) || cb == NULL)
|
||||
return UV_EINVAL;
|
||||
|
||||
if (uv__is_active(handle))
|
||||
uv_timer_stop(handle);
|
||||
|
||||
clamped_timeout = handle->loop->time + timeout;
|
||||
@ -87,7 +87,7 @@ int uv_timer_start(uv_timer_t* handle,
|
||||
handle->start_id = handle->loop->timer_counter++;
|
||||
|
||||
heap_insert(timer_heap(handle->loop),
|
||||
(struct heap_node*) &handle->heap_node,
|
||||
(struct heap_node*) &handle->node.heap,
|
||||
timer_less_than);
|
||||
uv__handle_start(handle);
|
||||
|
||||
@ -96,14 +96,16 @@ int uv_timer_start(uv_timer_t* handle,
|
||||
|
||||
|
||||
int uv_timer_stop(uv_timer_t* handle) {
|
||||
if (!uv__is_active(handle))
|
||||
return 0;
|
||||
|
||||
if (uv__is_active(handle)) {
|
||||
heap_remove(timer_heap(handle->loop),
|
||||
(struct heap_node*) &handle->heap_node,
|
||||
(struct heap_node*) &handle->node.heap,
|
||||
timer_less_than);
|
||||
uv__handle_stop(handle);
|
||||
} else {
|
||||
uv__queue_remove(&handle->node.queue);
|
||||
}
|
||||
|
||||
uv__queue_init(&handle->node.queue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -148,7 +150,7 @@ int uv__next_timeout(const uv_loop_t* loop) {
|
||||
if (heap_node == NULL)
|
||||
return -1; /* block indefinitely */
|
||||
|
||||
handle = container_of(heap_node, uv_timer_t, heap_node);
|
||||
handle = container_of(heap_node, uv_timer_t, node.heap);
|
||||
if (handle->timeout <= loop->time)
|
||||
return 0;
|
||||
|
||||
@ -163,17 +165,30 @@ int uv__next_timeout(const uv_loop_t* loop) {
|
||||
void uv__run_timers(uv_loop_t* loop) {
|
||||
struct heap_node* heap_node;
|
||||
uv_timer_t* handle;
|
||||
struct uv__queue* queue_node;
|
||||
struct uv__queue ready_queue;
|
||||
|
||||
uv__queue_init(&ready_queue);
|
||||
|
||||
for (;;) {
|
||||
heap_node = heap_min(timer_heap(loop));
|
||||
if (heap_node == NULL)
|
||||
break;
|
||||
|
||||
handle = container_of(heap_node, uv_timer_t, heap_node);
|
||||
handle = container_of(heap_node, uv_timer_t, node.heap);
|
||||
if (handle->timeout > loop->time)
|
||||
break;
|
||||
|
||||
uv_timer_stop(handle);
|
||||
uv__queue_insert_tail(&ready_queue, &handle->node.queue);
|
||||
}
|
||||
|
||||
while (!uv__queue_empty(&ready_queue)) {
|
||||
queue_node = uv__queue_head(&ready_queue);
|
||||
uv__queue_remove(queue_node);
|
||||
uv__queue_init(queue_node);
|
||||
handle = container_of(queue_node, uv_timer_t, node.queue);
|
||||
|
||||
uv_timer_again(handle);
|
||||
handle->timer_cb(handle);
|
||||
}
|
||||
|
||||
@ -131,11 +131,12 @@ int uv__io_check_fd(uv_loop_t* loop, int fd) {
|
||||
|
||||
|
||||
void uv__io_poll(uv_loop_t* loop, int timeout) {
|
||||
uv__loop_internal_fields_t* lfields;
|
||||
struct pollfd events[1024];
|
||||
struct pollfd pqry;
|
||||
struct pollfd* pe;
|
||||
struct poll_ctl pc;
|
||||
QUEUE* q;
|
||||
struct uv__queue* q;
|
||||
uv__io_t* w;
|
||||
uint64_t base;
|
||||
uint64_t diff;
|
||||
@ -150,16 +151,18 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
|
||||
int reset_timeout;
|
||||
|
||||
if (loop->nfds == 0) {
|
||||
assert(QUEUE_EMPTY(&loop->watcher_queue));
|
||||
assert(uv__queue_empty(&loop->watcher_queue));
|
||||
return;
|
||||
}
|
||||
|
||||
while (!QUEUE_EMPTY(&loop->watcher_queue)) {
|
||||
q = QUEUE_HEAD(&loop->watcher_queue);
|
||||
QUEUE_REMOVE(q);
|
||||
QUEUE_INIT(q);
|
||||
lfields = uv__get_internal_fields(loop);
|
||||
|
||||
w = QUEUE_DATA(q, uv__io_t, watcher_queue);
|
||||
while (!uv__queue_empty(&loop->watcher_queue)) {
|
||||
q = uv__queue_head(&loop->watcher_queue);
|
||||
uv__queue_remove(q);
|
||||
uv__queue_init(q);
|
||||
|
||||
w = uv__queue_data(q, uv__io_t, watcher_queue);
|
||||
assert(w->pevents != 0);
|
||||
assert(w->fd >= 0);
|
||||
assert(w->fd < (int) loop->nwatchers);
|
||||
@ -217,7 +220,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
|
||||
base = loop->time;
|
||||
count = 48; /* Benchmarks suggest this gives the best throughput. */
|
||||
|
||||
if (uv__get_internal_fields(loop)->flags & UV_METRICS_IDLE_TIME) {
|
||||
if (lfields->flags & UV_METRICS_IDLE_TIME) {
|
||||
reset_timeout = 1;
|
||||
user_timeout = timeout;
|
||||
timeout = 0;
|
||||
@ -232,6 +235,12 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
|
||||
if (timeout != 0)
|
||||
uv__metrics_set_provider_entry_time(loop);
|
||||
|
||||
/* Store the current timeout in a location that's globally accessible so
|
||||
* other locations like uv__work_done() can determine whether the queue
|
||||
* of events in the callback were waiting when poll was called.
|
||||
*/
|
||||
lfields->current_timeout = timeout;
|
||||
|
||||
nfds = pollset_poll(loop->backend_fd,
|
||||
events,
|
||||
ARRAY_SIZE(events),
|
||||
@ -321,9 +330,11 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
|
||||
nevents++;
|
||||
}
|
||||
|
||||
uv__metrics_inc_events(loop, nevents);
|
||||
if (reset_timeout != 0) {
|
||||
timeout = user_timeout;
|
||||
reset_timeout = 0;
|
||||
uv__metrics_inc_events_waiting(loop, nevents);
|
||||
}
|
||||
|
||||
if (have_signals != 0) {
|
||||
@ -389,6 +400,11 @@ uint64_t uv_get_constrained_memory(void) {
|
||||
}
|
||||
|
||||
|
||||
uint64_t uv_get_available_memory(void) {
|
||||
return uv_get_free_memory();
|
||||
}
|
||||
|
||||
|
||||
void uv_loadavg(double avg[3]) {
|
||||
perfstat_cpu_total_t ps_total;
|
||||
int result = perfstat_cpu_total(NULL, &ps_total, sizeof(ps_total), 1);
|
||||
@ -425,7 +441,7 @@ static char* uv__rawname(const char* cp, char (*dst)[FILENAME_MAX+1]) {
|
||||
static int uv__path_is_a_directory(char* filename) {
|
||||
struct stat statbuf;
|
||||
|
||||
if (stat(filename, &statbuf) < 0)
|
||||
if (uv__stat(filename, &statbuf) < 0)
|
||||
return -1; /* failed: not a directory, assume it is a file */
|
||||
|
||||
if (statbuf.st_type == VDIR)
|
||||
@ -1104,6 +1120,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
|
||||
struct ifreq *ifr, *p, flg;
|
||||
struct in6_ifreq if6;
|
||||
struct sockaddr_dl* sa_addr;
|
||||
size_t namelen;
|
||||
char* name;
|
||||
|
||||
ifc.ifc_req = NULL;
|
||||
sock6fd = -1;
|
||||
@ -1140,6 +1158,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
|
||||
#define ADDR_SIZE(p) MAX((p).sa_len, sizeof(p))
|
||||
|
||||
/* Count all up and running ipv4/ipv6 addresses */
|
||||
namelen = 0;
|
||||
ifr = ifc.ifc_req;
|
||||
while ((char*)ifr < (char*)ifc.ifc_req + ifc.ifc_len) {
|
||||
p = ifr;
|
||||
@ -1159,6 +1178,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
|
||||
if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING))
|
||||
continue;
|
||||
|
||||
namelen += strlen(ent->ifa_name) + 1;
|
||||
(*count)++;
|
||||
}
|
||||
|
||||
@ -1166,8 +1186,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
|
||||
goto cleanup;
|
||||
|
||||
/* Alloc the return interface structs */
|
||||
*addresses = uv__calloc(*count, sizeof(**addresses));
|
||||
if (!(*addresses)) {
|
||||
*addresses = uv__calloc(1, *count * sizeof(**addresses) + namelen);
|
||||
if (*addresses == NULL) {
|
||||
r = UV_ENOMEM;
|
||||
goto cleanup;
|
||||
}
|
||||
@ -1194,7 +1214,9 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
|
||||
|
||||
/* All conditions above must match count loop */
|
||||
|
||||
address->name = uv__strdup(p->ifr_name);
|
||||
namelen = strlen(p->ifr_name) + 1;
|
||||
address->name = memcpy(name, p->ifr_name, namelen);
|
||||
name += namelen;
|
||||
|
||||
if (inet6)
|
||||
address->address.address6 = *((struct sockaddr_in6*) &p->ifr_addr);
|
||||
@ -1267,12 +1289,6 @@ cleanup:
|
||||
|
||||
void uv_free_interface_addresses(uv_interface_address_t* addresses,
|
||||
int count) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < count; ++i) {
|
||||
uv__free(addresses[i].name);
|
||||
}
|
||||
|
||||
uv__free(addresses);
|
||||
}
|
||||
|
||||
|
||||
@ -1,713 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2013, Kenneth MacKay
|
||||
Copyright (c) 2014, Emergya (Cloud4all, FP7/2007-2013 grant agreement #289016)
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "uv/android-ifaddrs.h"
|
||||
#include "uv-common.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <net/if_arp.h>
|
||||
#include <netinet/in.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <linux/if_packet.h>
|
||||
|
||||
typedef struct NetlinkList
|
||||
{
|
||||
struct NetlinkList *m_next;
|
||||
struct nlmsghdr *m_data;
|
||||
unsigned int m_size;
|
||||
} NetlinkList;
|
||||
|
||||
static int netlink_socket(pid_t *p_pid)
|
||||
{
|
||||
struct sockaddr_nl l_addr;
|
||||
socklen_t l_len;
|
||||
|
||||
int l_socket = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
|
||||
if(l_socket < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(&l_addr, 0, sizeof(l_addr));
|
||||
l_addr.nl_family = AF_NETLINK;
|
||||
if(bind(l_socket, (struct sockaddr *)&l_addr, sizeof(l_addr)) < 0)
|
||||
{
|
||||
close(l_socket);
|
||||
return -1;
|
||||
}
|
||||
|
||||
l_len = sizeof(l_addr);
|
||||
if(getsockname(l_socket, (struct sockaddr *)&l_addr, &l_len) < 0)
|
||||
{
|
||||
close(l_socket);
|
||||
return -1;
|
||||
}
|
||||
*p_pid = l_addr.nl_pid;
|
||||
|
||||
return l_socket;
|
||||
}
|
||||
|
||||
static int netlink_send(int p_socket, int p_request)
|
||||
{
|
||||
char l_buffer[NLMSG_ALIGN(sizeof(struct nlmsghdr)) + NLMSG_ALIGN(sizeof(struct rtgenmsg))];
|
||||
|
||||
struct nlmsghdr *l_hdr;
|
||||
struct rtgenmsg *l_msg;
|
||||
struct sockaddr_nl l_addr;
|
||||
|
||||
memset(l_buffer, 0, sizeof(l_buffer));
|
||||
|
||||
l_hdr = (struct nlmsghdr *)l_buffer;
|
||||
l_msg = (struct rtgenmsg *)NLMSG_DATA(l_hdr);
|
||||
|
||||
l_hdr->nlmsg_len = NLMSG_LENGTH(sizeof(*l_msg));
|
||||
l_hdr->nlmsg_type = p_request;
|
||||
l_hdr->nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
|
||||
l_hdr->nlmsg_pid = 0;
|
||||
l_hdr->nlmsg_seq = p_socket;
|
||||
l_msg->rtgen_family = AF_UNSPEC;
|
||||
|
||||
memset(&l_addr, 0, sizeof(l_addr));
|
||||
l_addr.nl_family = AF_NETLINK;
|
||||
return (sendto(p_socket, l_hdr, l_hdr->nlmsg_len, 0, (struct sockaddr *)&l_addr, sizeof(l_addr)));
|
||||
}
|
||||
|
||||
static int netlink_recv(int p_socket, void *p_buffer, size_t p_len)
|
||||
{
|
||||
struct sockaddr_nl l_addr;
|
||||
struct msghdr l_msg;
|
||||
|
||||
struct iovec l_iov;
|
||||
l_iov.iov_base = p_buffer;
|
||||
l_iov.iov_len = p_len;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
int l_result;
|
||||
l_msg.msg_name = (void *)&l_addr;
|
||||
l_msg.msg_namelen = sizeof(l_addr);
|
||||
l_msg.msg_iov = &l_iov;
|
||||
l_msg.msg_iovlen = 1;
|
||||
l_msg.msg_control = NULL;
|
||||
l_msg.msg_controllen = 0;
|
||||
l_msg.msg_flags = 0;
|
||||
l_result = recvmsg(p_socket, &l_msg, 0);
|
||||
|
||||
if(l_result < 0)
|
||||
{
|
||||
if(errno == EINTR)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
return -2;
|
||||
}
|
||||
|
||||
/* Buffer was too small */
|
||||
if(l_msg.msg_flags & MSG_TRUNC)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return l_result;
|
||||
}
|
||||
}
|
||||
|
||||
static struct nlmsghdr *getNetlinkResponse(int p_socket, pid_t p_pid, int *p_size, int *p_done)
|
||||
{
|
||||
size_t l_size = 4096;
|
||||
void *l_buffer = NULL;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
int l_read;
|
||||
|
||||
uv__free(l_buffer);
|
||||
l_buffer = uv__malloc(l_size);
|
||||
if (l_buffer == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
l_read = netlink_recv(p_socket, l_buffer, l_size);
|
||||
*p_size = l_read;
|
||||
if(l_read == -2)
|
||||
{
|
||||
uv__free(l_buffer);
|
||||
return NULL;
|
||||
}
|
||||
if(l_read >= 0)
|
||||
{
|
||||
struct nlmsghdr *l_hdr;
|
||||
for(l_hdr = (struct nlmsghdr *)l_buffer; NLMSG_OK(l_hdr, (unsigned int)l_read); l_hdr = (struct nlmsghdr *)NLMSG_NEXT(l_hdr, l_read))
|
||||
{
|
||||
if((pid_t)l_hdr->nlmsg_pid != p_pid || (int)l_hdr->nlmsg_seq != p_socket)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if(l_hdr->nlmsg_type == NLMSG_DONE)
|
||||
{
|
||||
*p_done = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if(l_hdr->nlmsg_type == NLMSG_ERROR)
|
||||
{
|
||||
uv__free(l_buffer);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return l_buffer;
|
||||
}
|
||||
|
||||
l_size *= 2;
|
||||
}
|
||||
}
|
||||
|
||||
static NetlinkList *newListItem(struct nlmsghdr *p_data, unsigned int p_size)
|
||||
{
|
||||
NetlinkList *l_item = uv__malloc(sizeof(NetlinkList));
|
||||
if (l_item == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
l_item->m_next = NULL;
|
||||
l_item->m_data = p_data;
|
||||
l_item->m_size = p_size;
|
||||
return l_item;
|
||||
}
|
||||
|
||||
static void freeResultList(NetlinkList *p_list)
|
||||
{
|
||||
NetlinkList *l_cur;
|
||||
while(p_list)
|
||||
{
|
||||
l_cur = p_list;
|
||||
p_list = p_list->m_next;
|
||||
uv__free(l_cur->m_data);
|
||||
uv__free(l_cur);
|
||||
}
|
||||
}
|
||||
|
||||
static NetlinkList *getResultList(int p_socket, int p_request, pid_t p_pid)
|
||||
{
|
||||
int l_size;
|
||||
int l_done;
|
||||
NetlinkList *l_list;
|
||||
NetlinkList *l_end;
|
||||
|
||||
if(netlink_send(p_socket, p_request) < 0)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
l_list = NULL;
|
||||
l_end = NULL;
|
||||
|
||||
l_done = 0;
|
||||
while(!l_done)
|
||||
{
|
||||
NetlinkList *l_item;
|
||||
|
||||
struct nlmsghdr *l_hdr = getNetlinkResponse(p_socket, p_pid, &l_size, &l_done);
|
||||
/* Error */
|
||||
if(!l_hdr)
|
||||
{
|
||||
freeResultList(l_list);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
l_item = newListItem(l_hdr, l_size);
|
||||
if (!l_item)
|
||||
{
|
||||
freeResultList(l_list);
|
||||
return NULL;
|
||||
}
|
||||
if(!l_list)
|
||||
{
|
||||
l_list = l_item;
|
||||
}
|
||||
else
|
||||
{
|
||||
l_end->m_next = l_item;
|
||||
}
|
||||
l_end = l_item;
|
||||
}
|
||||
return l_list;
|
||||
}
|
||||
|
||||
static size_t maxSize(size_t a, size_t b)
|
||||
{
|
||||
return (a > b ? a : b);
|
||||
}
|
||||
|
||||
static size_t calcAddrLen(sa_family_t p_family, int p_dataSize)
|
||||
{
|
||||
switch(p_family)
|
||||
{
|
||||
case AF_INET:
|
||||
return sizeof(struct sockaddr_in);
|
||||
case AF_INET6:
|
||||
return sizeof(struct sockaddr_in6);
|
||||
case AF_PACKET:
|
||||
return maxSize(sizeof(struct sockaddr_ll), offsetof(struct sockaddr_ll, sll_addr) + p_dataSize);
|
||||
default:
|
||||
return maxSize(sizeof(struct sockaddr), offsetof(struct sockaddr, sa_data) + p_dataSize);
|
||||
}
|
||||
}
|
||||
|
||||
static void makeSockaddr(sa_family_t p_family, struct sockaddr *p_dest, void *p_data, size_t p_size)
|
||||
{
|
||||
switch(p_family)
|
||||
{
|
||||
case AF_INET:
|
||||
memcpy(&((struct sockaddr_in*)p_dest)->sin_addr, p_data, p_size);
|
||||
break;
|
||||
case AF_INET6:
|
||||
memcpy(&((struct sockaddr_in6*)p_dest)->sin6_addr, p_data, p_size);
|
||||
break;
|
||||
case AF_PACKET:
|
||||
memcpy(((struct sockaddr_ll*)p_dest)->sll_addr, p_data, p_size);
|
||||
((struct sockaddr_ll*)p_dest)->sll_halen = p_size;
|
||||
break;
|
||||
default:
|
||||
memcpy(p_dest->sa_data, p_data, p_size);
|
||||
break;
|
||||
}
|
||||
p_dest->sa_family = p_family;
|
||||
}
|
||||
|
||||
static void addToEnd(struct ifaddrs **p_resultList, struct ifaddrs *p_entry)
|
||||
{
|
||||
if(!*p_resultList)
|
||||
{
|
||||
*p_resultList = p_entry;
|
||||
}
|
||||
else
|
||||
{
|
||||
struct ifaddrs *l_cur = *p_resultList;
|
||||
while(l_cur->ifa_next)
|
||||
{
|
||||
l_cur = l_cur->ifa_next;
|
||||
}
|
||||
l_cur->ifa_next = p_entry;
|
||||
}
|
||||
}
|
||||
|
||||
static int interpretLink(struct nlmsghdr *p_hdr, struct ifaddrs **p_resultList)
|
||||
{
|
||||
struct ifaddrs *l_entry;
|
||||
|
||||
char *l_index;
|
||||
char *l_name;
|
||||
char *l_addr;
|
||||
char *l_data;
|
||||
|
||||
struct ifinfomsg *l_info = (struct ifinfomsg *)NLMSG_DATA(p_hdr);
|
||||
|
||||
size_t l_nameSize = 0;
|
||||
size_t l_addrSize = 0;
|
||||
size_t l_dataSize = 0;
|
||||
|
||||
size_t l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifinfomsg));
|
||||
struct rtattr *l_rta;
|
||||
for(l_rta = IFLA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
|
||||
{
|
||||
size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
|
||||
switch(l_rta->rta_type)
|
||||
{
|
||||
case IFLA_ADDRESS:
|
||||
case IFLA_BROADCAST:
|
||||
l_addrSize += NLMSG_ALIGN(calcAddrLen(AF_PACKET, l_rtaDataSize));
|
||||
break;
|
||||
case IFLA_IFNAME:
|
||||
l_nameSize += NLMSG_ALIGN(l_rtaSize + 1);
|
||||
break;
|
||||
case IFLA_STATS:
|
||||
l_dataSize += NLMSG_ALIGN(l_rtaSize);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
l_entry = uv__malloc(sizeof(struct ifaddrs) + sizeof(int) + l_nameSize + l_addrSize + l_dataSize);
|
||||
if (l_entry == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
memset(l_entry, 0, sizeof(struct ifaddrs));
|
||||
l_entry->ifa_name = "";
|
||||
|
||||
l_index = ((char *)l_entry) + sizeof(struct ifaddrs);
|
||||
l_name = l_index + sizeof(int);
|
||||
l_addr = l_name + l_nameSize;
|
||||
l_data = l_addr + l_addrSize;
|
||||
|
||||
/* Save the interface index so we can look it up when handling the
|
||||
* addresses.
|
||||
*/
|
||||
memcpy(l_index, &l_info->ifi_index, sizeof(int));
|
||||
|
||||
l_entry->ifa_flags = l_info->ifi_flags;
|
||||
|
||||
l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifinfomsg));
|
||||
for(l_rta = IFLA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
|
||||
{
|
||||
void *l_rtaData = RTA_DATA(l_rta);
|
||||
size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
|
||||
switch(l_rta->rta_type)
|
||||
{
|
||||
case IFLA_ADDRESS:
|
||||
case IFLA_BROADCAST:
|
||||
{
|
||||
size_t l_addrLen = calcAddrLen(AF_PACKET, l_rtaDataSize);
|
||||
makeSockaddr(AF_PACKET, (struct sockaddr *)l_addr, l_rtaData, l_rtaDataSize);
|
||||
((struct sockaddr_ll *)l_addr)->sll_ifindex = l_info->ifi_index;
|
||||
((struct sockaddr_ll *)l_addr)->sll_hatype = l_info->ifi_type;
|
||||
if(l_rta->rta_type == IFLA_ADDRESS)
|
||||
{
|
||||
l_entry->ifa_addr = (struct sockaddr *)l_addr;
|
||||
}
|
||||
else
|
||||
{
|
||||
l_entry->ifa_broadaddr = (struct sockaddr *)l_addr;
|
||||
}
|
||||
l_addr += NLMSG_ALIGN(l_addrLen);
|
||||
break;
|
||||
}
|
||||
case IFLA_IFNAME:
|
||||
strncpy(l_name, l_rtaData, l_rtaDataSize);
|
||||
l_name[l_rtaDataSize] = '\0';
|
||||
l_entry->ifa_name = l_name;
|
||||
break;
|
||||
case IFLA_STATS:
|
||||
memcpy(l_data, l_rtaData, l_rtaDataSize);
|
||||
l_entry->ifa_data = l_data;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
addToEnd(p_resultList, l_entry);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ifaddrs *findInterface(int p_index, struct ifaddrs **p_links, int p_numLinks)
|
||||
{
|
||||
int l_num = 0;
|
||||
struct ifaddrs *l_cur = *p_links;
|
||||
while(l_cur && l_num < p_numLinks)
|
||||
{
|
||||
char *l_indexPtr = ((char *)l_cur) + sizeof(struct ifaddrs);
|
||||
int l_index;
|
||||
memcpy(&l_index, l_indexPtr, sizeof(int));
|
||||
if(l_index == p_index)
|
||||
{
|
||||
return l_cur;
|
||||
}
|
||||
|
||||
l_cur = l_cur->ifa_next;
|
||||
++l_num;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int interpretAddr(struct nlmsghdr *p_hdr, struct ifaddrs **p_resultList, int p_numLinks)
|
||||
{
|
||||
struct ifaddrmsg *l_info = (struct ifaddrmsg *)NLMSG_DATA(p_hdr);
|
||||
struct ifaddrs *l_interface = findInterface(l_info->ifa_index, p_resultList, p_numLinks);
|
||||
|
||||
size_t l_nameSize = 0;
|
||||
size_t l_addrSize = 0;
|
||||
|
||||
int l_addedNetmask = 0;
|
||||
|
||||
size_t l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifaddrmsg));
|
||||
struct rtattr *l_rta;
|
||||
struct ifaddrs *l_entry;
|
||||
|
||||
char *l_name;
|
||||
char *l_addr;
|
||||
|
||||
for(l_rta = IFA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
|
||||
{
|
||||
size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
|
||||
if(l_info->ifa_family == AF_PACKET)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
switch(l_rta->rta_type)
|
||||
{
|
||||
case IFA_ADDRESS:
|
||||
case IFA_LOCAL:
|
||||
l_addrSize += NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize));
|
||||
if((l_info->ifa_family == AF_INET || l_info->ifa_family == AF_INET6) && !l_addedNetmask)
|
||||
{
|
||||
/* Make room for netmask */
|
||||
l_addrSize += NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize));
|
||||
l_addedNetmask = 1;
|
||||
}
|
||||
break;
|
||||
case IFA_BROADCAST:
|
||||
l_addrSize += NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize));
|
||||
break;
|
||||
case IFA_LABEL:
|
||||
l_nameSize += NLMSG_ALIGN(l_rtaDataSize + 1);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
l_entry = uv__malloc(sizeof(struct ifaddrs) + l_nameSize + l_addrSize);
|
||||
if (l_entry == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
memset(l_entry, 0, sizeof(struct ifaddrs));
|
||||
l_entry->ifa_name = (l_interface ? l_interface->ifa_name : "");
|
||||
|
||||
l_name = ((char *)l_entry) + sizeof(struct ifaddrs);
|
||||
l_addr = l_name + l_nameSize;
|
||||
|
||||
l_entry->ifa_flags = l_info->ifa_flags;
|
||||
if(l_interface)
|
||||
{
|
||||
l_entry->ifa_flags |= l_interface->ifa_flags;
|
||||
}
|
||||
|
||||
l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifaddrmsg));
|
||||
for(l_rta = IFA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
|
||||
{
|
||||
void *l_rtaData = RTA_DATA(l_rta);
|
||||
size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
|
||||
switch(l_rta->rta_type)
|
||||
{
|
||||
case IFA_ADDRESS:
|
||||
case IFA_BROADCAST:
|
||||
case IFA_LOCAL:
|
||||
{
|
||||
size_t l_addrLen = calcAddrLen(l_info->ifa_family, l_rtaDataSize);
|
||||
makeSockaddr(l_info->ifa_family, (struct sockaddr *)l_addr, l_rtaData, l_rtaDataSize);
|
||||
if(l_info->ifa_family == AF_INET6)
|
||||
{
|
||||
if(IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)l_rtaData) || IN6_IS_ADDR_MC_LINKLOCAL((struct in6_addr *)l_rtaData))
|
||||
{
|
||||
((struct sockaddr_in6 *)l_addr)->sin6_scope_id = l_info->ifa_index;
|
||||
}
|
||||
}
|
||||
|
||||
/* Apparently in a point-to-point network IFA_ADDRESS contains
|
||||
* the dest address and IFA_LOCAL contains the local address
|
||||
*/
|
||||
if(l_rta->rta_type == IFA_ADDRESS)
|
||||
{
|
||||
if(l_entry->ifa_addr)
|
||||
{
|
||||
l_entry->ifa_dstaddr = (struct sockaddr *)l_addr;
|
||||
}
|
||||
else
|
||||
{
|
||||
l_entry->ifa_addr = (struct sockaddr *)l_addr;
|
||||
}
|
||||
}
|
||||
else if(l_rta->rta_type == IFA_LOCAL)
|
||||
{
|
||||
if(l_entry->ifa_addr)
|
||||
{
|
||||
l_entry->ifa_dstaddr = l_entry->ifa_addr;
|
||||
}
|
||||
l_entry->ifa_addr = (struct sockaddr *)l_addr;
|
||||
}
|
||||
else
|
||||
{
|
||||
l_entry->ifa_broadaddr = (struct sockaddr *)l_addr;
|
||||
}
|
||||
l_addr += NLMSG_ALIGN(l_addrLen);
|
||||
break;
|
||||
}
|
||||
case IFA_LABEL:
|
||||
strncpy(l_name, l_rtaData, l_rtaDataSize);
|
||||
l_name[l_rtaDataSize] = '\0';
|
||||
l_entry->ifa_name = l_name;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(l_entry->ifa_addr && (l_entry->ifa_addr->sa_family == AF_INET || l_entry->ifa_addr->sa_family == AF_INET6))
|
||||
{
|
||||
unsigned l_maxPrefix = (l_entry->ifa_addr->sa_family == AF_INET ? 32 : 128);
|
||||
unsigned l_prefix = (l_info->ifa_prefixlen > l_maxPrefix ? l_maxPrefix : l_info->ifa_prefixlen);
|
||||
unsigned char l_mask[16] = {0};
|
||||
unsigned i;
|
||||
for(i=0; i<(l_prefix/8); ++i)
|
||||
{
|
||||
l_mask[i] = 0xff;
|
||||
}
|
||||
if(l_prefix % 8)
|
||||
{
|
||||
l_mask[i] = 0xff << (8 - (l_prefix % 8));
|
||||
}
|
||||
|
||||
makeSockaddr(l_entry->ifa_addr->sa_family, (struct sockaddr *)l_addr, l_mask, l_maxPrefix / 8);
|
||||
l_entry->ifa_netmask = (struct sockaddr *)l_addr;
|
||||
}
|
||||
|
||||
addToEnd(p_resultList, l_entry);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int interpretLinks(int p_socket, pid_t p_pid, NetlinkList *p_netlinkList, struct ifaddrs **p_resultList)
|
||||
{
|
||||
|
||||
int l_numLinks = 0;
|
||||
for(; p_netlinkList; p_netlinkList = p_netlinkList->m_next)
|
||||
{
|
||||
unsigned int l_nlsize = p_netlinkList->m_size;
|
||||
struct nlmsghdr *l_hdr;
|
||||
for(l_hdr = p_netlinkList->m_data; NLMSG_OK(l_hdr, l_nlsize); l_hdr = NLMSG_NEXT(l_hdr, l_nlsize))
|
||||
{
|
||||
if((pid_t)l_hdr->nlmsg_pid != p_pid || (int)l_hdr->nlmsg_seq != p_socket)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if(l_hdr->nlmsg_type == NLMSG_DONE)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if(l_hdr->nlmsg_type == RTM_NEWLINK)
|
||||
{
|
||||
if(interpretLink(l_hdr, p_resultList) == -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
++l_numLinks;
|
||||
}
|
||||
}
|
||||
}
|
||||
return l_numLinks;
|
||||
}
|
||||
|
||||
static int interpretAddrs(int p_socket, pid_t p_pid, NetlinkList *p_netlinkList, struct ifaddrs **p_resultList, int p_numLinks)
|
||||
{
|
||||
for(; p_netlinkList; p_netlinkList = p_netlinkList->m_next)
|
||||
{
|
||||
unsigned int l_nlsize = p_netlinkList->m_size;
|
||||
struct nlmsghdr *l_hdr;
|
||||
for(l_hdr = p_netlinkList->m_data; NLMSG_OK(l_hdr, l_nlsize); l_hdr = NLMSG_NEXT(l_hdr, l_nlsize))
|
||||
{
|
||||
if((pid_t)l_hdr->nlmsg_pid != p_pid || (int)l_hdr->nlmsg_seq != p_socket)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if(l_hdr->nlmsg_type == NLMSG_DONE)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if(l_hdr->nlmsg_type == RTM_NEWADDR)
|
||||
{
|
||||
if (interpretAddr(l_hdr, p_resultList, p_numLinks) == -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int getifaddrs(struct ifaddrs **ifap)
|
||||
{
|
||||
int l_socket;
|
||||
int l_result;
|
||||
int l_numLinks;
|
||||
pid_t l_pid;
|
||||
NetlinkList *l_linkResults;
|
||||
NetlinkList *l_addrResults;
|
||||
|
||||
if(!ifap)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
*ifap = NULL;
|
||||
|
||||
l_socket = netlink_socket(&l_pid);
|
||||
if(l_socket < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
l_linkResults = getResultList(l_socket, RTM_GETLINK, l_pid);
|
||||
if(!l_linkResults)
|
||||
{
|
||||
close(l_socket);
|
||||
return -1;
|
||||
}
|
||||
|
||||
l_addrResults = getResultList(l_socket, RTM_GETADDR, l_pid);
|
||||
if(!l_addrResults)
|
||||
{
|
||||
close(l_socket);
|
||||
freeResultList(l_linkResults);
|
||||
return -1;
|
||||
}
|
||||
|
||||
l_result = 0;
|
||||
l_numLinks = interpretLinks(l_socket, l_pid, l_linkResults, ifap);
|
||||
if(l_numLinks == -1 || interpretAddrs(l_socket, l_pid, l_addrResults, ifap, l_numLinks) == -1)
|
||||
{
|
||||
l_result = -1;
|
||||
}
|
||||
|
||||
freeResultList(l_linkResults);
|
||||
freeResultList(l_addrResults);
|
||||
close(l_socket);
|
||||
return l_result;
|
||||
}
|
||||
|
||||
void freeifaddrs(struct ifaddrs *ifa)
|
||||
{
|
||||
struct ifaddrs *l_cur;
|
||||
while(ifa)
|
||||
{
|
||||
l_cur = ifa;
|
||||
ifa = ifa->ifa_next;
|
||||
uv__free(l_cur);
|
||||
}
|
||||
}
|
||||
247
src/unix/async.c
247
src/unix/async.c
@ -24,9 +24,9 @@
|
||||
|
||||
#include "uv.h"
|
||||
#include "internal.h"
|
||||
#include "atomic-ops.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdatomic.h>
|
||||
#include <stdio.h> /* snprintf() */
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
@ -38,8 +38,37 @@
|
||||
#include <sys/eventfd.h>
|
||||
#endif
|
||||
|
||||
#if UV__KQUEUE_EVFILT_USER
|
||||
static uv_once_t kqueue_runtime_detection_guard = UV_ONCE_INIT;
|
||||
static int kqueue_evfilt_user_support = 1;
|
||||
|
||||
|
||||
static void uv__kqueue_runtime_detection(void) {
|
||||
int kq;
|
||||
struct kevent ev[2];
|
||||
struct timespec timeout = {0, 0};
|
||||
|
||||
/* Perform the runtime detection to ensure that kqueue with
|
||||
* EVFILT_USER actually works. */
|
||||
kq = kqueue();
|
||||
EV_SET(ev, UV__KQUEUE_EVFILT_USER_IDENT, EVFILT_USER,
|
||||
EV_ADD | EV_CLEAR, 0, 0, 0);
|
||||
EV_SET(ev + 1, UV__KQUEUE_EVFILT_USER_IDENT, EVFILT_USER,
|
||||
0, NOTE_TRIGGER, 0, 0);
|
||||
if (kevent(kq, ev, 2, ev, 1, &timeout) < 1 ||
|
||||
ev[0].filter != EVFILT_USER ||
|
||||
ev[0].ident != UV__KQUEUE_EVFILT_USER_IDENT ||
|
||||
ev[0].flags & EV_ERROR)
|
||||
/* If we wind up here, we can assume that EVFILT_USER is defined but
|
||||
* broken on the current system. */
|
||||
kqueue_evfilt_user_support = 0;
|
||||
uv__close(kq);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void uv__async_send(uv_loop_t* loop);
|
||||
static int uv__async_start(uv_loop_t* loop);
|
||||
static void uv__cpu_relax(void);
|
||||
|
||||
|
||||
int uv_async_init(uv_loop_t* loop, uv_async_t* handle, uv_async_cb async_cb) {
|
||||
@ -52,8 +81,9 @@ int uv_async_init(uv_loop_t* loop, uv_async_t* handle, uv_async_cb async_cb) {
|
||||
uv__handle_init(loop, (uv_handle_t*)handle, UV_ASYNC);
|
||||
handle->async_cb = async_cb;
|
||||
handle->pending = 0;
|
||||
handle->u.fd = 0; /* This will be used as a busy flag. */
|
||||
|
||||
QUEUE_INSERT_TAIL(&loop->async_handles, &handle->queue);
|
||||
uv__queue_insert_tail(&loop->async_handles, &handle->queue);
|
||||
uv__handle_start(handle);
|
||||
|
||||
return 0;
|
||||
@ -61,46 +91,54 @@ int uv_async_init(uv_loop_t* loop, uv_async_t* handle, uv_async_cb async_cb) {
|
||||
|
||||
|
||||
int uv_async_send(uv_async_t* handle) {
|
||||
_Atomic int* pending;
|
||||
_Atomic int* busy;
|
||||
|
||||
pending = (_Atomic int*) &handle->pending;
|
||||
busy = (_Atomic int*) &handle->u.fd;
|
||||
|
||||
/* Do a cheap read first. */
|
||||
if (ACCESS_ONCE(int, handle->pending) != 0)
|
||||
if (atomic_load_explicit(pending, memory_order_relaxed) != 0)
|
||||
return 0;
|
||||
|
||||
/* Tell the other thread we're busy with the handle. */
|
||||
if (cmpxchgi(&handle->pending, 0, 1) != 0)
|
||||
return 0;
|
||||
/* Set the loop to busy. */
|
||||
atomic_fetch_add(busy, 1);
|
||||
|
||||
/* Wake up the other thread's event loop. */
|
||||
if (atomic_exchange(pending, 1) == 0)
|
||||
uv__async_send(handle->loop);
|
||||
|
||||
/* Tell the other thread we're done. */
|
||||
if (cmpxchgi(&handle->pending, 1, 2) != 1)
|
||||
abort();
|
||||
/* Set the loop to not-busy. */
|
||||
atomic_fetch_add(busy, -1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Only call this from the event loop thread. */
|
||||
static int uv__async_spin(uv_async_t* handle) {
|
||||
/* Wait for the busy flag to clear before closing.
|
||||
* Only call this from the event loop thread. */
|
||||
static void uv__async_spin(uv_async_t* handle) {
|
||||
_Atomic int* pending;
|
||||
_Atomic int* busy;
|
||||
int i;
|
||||
int rc;
|
||||
|
||||
pending = (_Atomic int*) &handle->pending;
|
||||
busy = (_Atomic int*) &handle->u.fd;
|
||||
|
||||
/* Set the pending flag first, so no new events will be added by other
|
||||
* threads after this function returns. */
|
||||
atomic_store(pending, 1);
|
||||
|
||||
for (;;) {
|
||||
/* 997 is not completely chosen at random. It's a prime number, acyclical
|
||||
* by nature, and should therefore hopefully dampen sympathetic resonance.
|
||||
/* 997 is not completely chosen at random. It's a prime number, acyclic by
|
||||
* nature, and should therefore hopefully dampen sympathetic resonance.
|
||||
*/
|
||||
for (i = 0; i < 997; i++) {
|
||||
/* rc=0 -- handle is not pending.
|
||||
* rc=1 -- handle is pending, other thread is still working with it.
|
||||
* rc=2 -- handle is pending, other thread is done.
|
||||
*/
|
||||
rc = cmpxchgi(&handle->pending, 2, 0);
|
||||
|
||||
if (rc != 1)
|
||||
return rc;
|
||||
if (atomic_load(busy) == 0)
|
||||
return;
|
||||
|
||||
/* Other thread is busy with this handle, spin until it's done. */
|
||||
cpu_relax();
|
||||
uv__cpu_relax();
|
||||
}
|
||||
|
||||
/* Yield the CPU. We may have preempted the other thread while it's
|
||||
@ -114,7 +152,7 @@ static int uv__async_spin(uv_async_t* handle) {
|
||||
|
||||
void uv__async_close(uv_async_t* handle) {
|
||||
uv__async_spin(handle);
|
||||
QUEUE_REMOVE(&handle->queue);
|
||||
uv__queue_remove(&handle->queue);
|
||||
uv__handle_stop(handle);
|
||||
}
|
||||
|
||||
@ -122,13 +160,18 @@ void uv__async_close(uv_async_t* handle) {
|
||||
static void uv__async_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
|
||||
char buf[1024];
|
||||
ssize_t r;
|
||||
QUEUE queue;
|
||||
QUEUE* q;
|
||||
struct uv__queue queue;
|
||||
struct uv__queue* q;
|
||||
uv_async_t* h;
|
||||
_Atomic int *pending;
|
||||
|
||||
assert(w == &loop->async_io_watcher);
|
||||
|
||||
#if UV__KQUEUE_EVFILT_USER
|
||||
for (;!kqueue_evfilt_user_support;) {
|
||||
#else
|
||||
for (;;) {
|
||||
#endif
|
||||
r = read(w->fd, buf, sizeof(buf));
|
||||
|
||||
if (r == sizeof(buf))
|
||||
@ -146,16 +189,18 @@ static void uv__async_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
|
||||
abort();
|
||||
}
|
||||
|
||||
QUEUE_MOVE(&loop->async_handles, &queue);
|
||||
while (!QUEUE_EMPTY(&queue)) {
|
||||
q = QUEUE_HEAD(&queue);
|
||||
h = QUEUE_DATA(q, uv_async_t, queue);
|
||||
uv__queue_move(&loop->async_handles, &queue);
|
||||
while (!uv__queue_empty(&queue)) {
|
||||
q = uv__queue_head(&queue);
|
||||
h = uv__queue_data(q, uv_async_t, queue);
|
||||
|
||||
QUEUE_REMOVE(q);
|
||||
QUEUE_INSERT_TAIL(&loop->async_handles, q);
|
||||
uv__queue_remove(q);
|
||||
uv__queue_insert_tail(&loop->async_handles, q);
|
||||
|
||||
if (0 == uv__async_spin(h))
|
||||
continue; /* Not pending. */
|
||||
/* Atomically fetch and clear pending flag */
|
||||
pending = (_Atomic int*) &h->pending;
|
||||
if (atomic_exchange(pending, 0) == 0)
|
||||
continue;
|
||||
|
||||
if (h->async_cb == NULL)
|
||||
continue;
|
||||
@ -182,6 +227,17 @@ static void uv__async_send(uv_loop_t* loop) {
|
||||
len = sizeof(val);
|
||||
fd = loop->async_io_watcher.fd; /* eventfd */
|
||||
}
|
||||
#elif UV__KQUEUE_EVFILT_USER
|
||||
struct kevent ev;
|
||||
|
||||
if (kqueue_evfilt_user_support) {
|
||||
fd = loop->async_io_watcher.fd; /* magic number for EVFILT_USER */
|
||||
EV_SET(&ev, fd, EVFILT_USER, 0, NOTE_TRIGGER, 0, 0);
|
||||
r = kevent(loop->backend_fd, &ev, 1, NULL, 0, NULL);
|
||||
if (r == 0)
|
||||
return;
|
||||
abort();
|
||||
}
|
||||
#endif
|
||||
|
||||
do
|
||||
@ -202,6 +258,9 @@ static void uv__async_send(uv_loop_t* loop) {
|
||||
static int uv__async_start(uv_loop_t* loop) {
|
||||
int pipefd[2];
|
||||
int err;
|
||||
#if UV__KQUEUE_EVFILT_USER
|
||||
struct kevent ev;
|
||||
#endif
|
||||
|
||||
if (loop->async_io_watcher.fd != -1)
|
||||
return 0;
|
||||
@ -213,6 +272,36 @@ static int uv__async_start(uv_loop_t* loop) {
|
||||
|
||||
pipefd[0] = err;
|
||||
pipefd[1] = -1;
|
||||
#elif UV__KQUEUE_EVFILT_USER
|
||||
uv_once(&kqueue_runtime_detection_guard, uv__kqueue_runtime_detection);
|
||||
if (kqueue_evfilt_user_support) {
|
||||
/* In order not to break the generic pattern of I/O polling, a valid
|
||||
* file descriptor is required to take up a room in loop->watchers,
|
||||
* thus we create one for that, but this fd will not be actually used,
|
||||
* it's just a placeholder and magic number which is going to be closed
|
||||
* during the cleanup, as other FDs. */
|
||||
err = uv__open_cloexec("/", O_RDONLY);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
pipefd[0] = err;
|
||||
pipefd[1] = -1;
|
||||
|
||||
/* When using EVFILT_USER event to wake up the kqueue, this event must be
|
||||
* registered beforehand. Otherwise, calling kevent() to issue an
|
||||
* unregistered EVFILT_USER event will get an ENOENT.
|
||||
* Since uv__async_send() may happen before uv__io_poll() with multi-threads,
|
||||
* we can't defer this registration of EVFILT_USER event as we did for other
|
||||
* events, but must perform it right away. */
|
||||
EV_SET(&ev, err, EVFILT_USER, EV_ADD | EV_CLEAR, 0, 0, 0);
|
||||
err = kevent(loop->backend_fd, &ev, 1, NULL, 0, NULL);
|
||||
if (err < 0)
|
||||
return UV__ERR(errno);
|
||||
} else {
|
||||
err = uv__make_pipe(pipefd, UV_NONBLOCK_PIPE);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
#else
|
||||
err = uv__make_pipe(pipefd, UV_NONBLOCK_PIPE);
|
||||
if (err < 0)
|
||||
@ -223,24 +312,39 @@ static int uv__async_start(uv_loop_t* loop) {
|
||||
uv__io_start(loop, &loop->async_io_watcher, POLLIN);
|
||||
loop->async_wfd = pipefd[1];
|
||||
|
||||
#if UV__KQUEUE_EVFILT_USER
|
||||
/* Prevent the EVFILT_USER event from being added to kqueue redundantly
|
||||
* and mistakenly later in uv__io_poll(). */
|
||||
if (kqueue_evfilt_user_support)
|
||||
loop->async_io_watcher.events = loop->async_io_watcher.pevents;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int uv__async_fork(uv_loop_t* loop) {
|
||||
if (loop->async_io_watcher.fd == -1) /* never started */
|
||||
return 0;
|
||||
|
||||
uv__async_stop(loop);
|
||||
|
||||
return uv__async_start(loop);
|
||||
}
|
||||
|
||||
|
||||
void uv__async_stop(uv_loop_t* loop) {
|
||||
struct uv__queue queue;
|
||||
struct uv__queue* q;
|
||||
uv_async_t* h;
|
||||
|
||||
if (loop->async_io_watcher.fd == -1)
|
||||
return;
|
||||
|
||||
/* Make sure no other thread is accessing the async handle fd after the loop
|
||||
* cleanup.
|
||||
*/
|
||||
uv__queue_move(&loop->async_handles, &queue);
|
||||
while (!uv__queue_empty(&queue)) {
|
||||
q = uv__queue_head(&queue);
|
||||
h = uv__queue_data(q, uv_async_t, queue);
|
||||
|
||||
uv__queue_remove(q);
|
||||
uv__queue_insert_tail(&loop->async_handles, q);
|
||||
|
||||
uv__async_spin(h);
|
||||
}
|
||||
|
||||
if (loop->async_wfd != -1) {
|
||||
if (loop->async_wfd != loop->async_io_watcher.fd)
|
||||
uv__close(loop->async_wfd);
|
||||
@ -251,3 +355,58 @@ void uv__async_stop(uv_loop_t* loop) {
|
||||
uv__close(loop->async_io_watcher.fd);
|
||||
loop->async_io_watcher.fd = -1;
|
||||
}
|
||||
|
||||
|
||||
int uv__async_fork(uv_loop_t* loop) {
|
||||
struct uv__queue queue;
|
||||
struct uv__queue* q;
|
||||
uv_async_t* h;
|
||||
|
||||
if (loop->async_io_watcher.fd == -1) /* never started */
|
||||
return 0;
|
||||
|
||||
uv__queue_move(&loop->async_handles, &queue);
|
||||
while (!uv__queue_empty(&queue)) {
|
||||
q = uv__queue_head(&queue);
|
||||
h = uv__queue_data(q, uv_async_t, queue);
|
||||
|
||||
uv__queue_remove(q);
|
||||
uv__queue_insert_tail(&loop->async_handles, q);
|
||||
|
||||
/* The state of any thread that set pending is now likely corrupt in this
|
||||
* child because the user called fork, so just clear these flags and move
|
||||
* on. Calling most libc functions after `fork` is declared to be undefined
|
||||
* behavior anyways, unless async-signal-safe, for multithreaded programs
|
||||
* like libuv, and nothing interesting in pthreads is async-signal-safe.
|
||||
*/
|
||||
h->pending = 0;
|
||||
/* This is the busy flag, and we just abruptly lost all other threads. */
|
||||
h->u.fd = 0;
|
||||
}
|
||||
|
||||
/* Recreate these, since they still exist, but belong to the wrong pid now. */
|
||||
if (loop->async_wfd != -1) {
|
||||
if (loop->async_wfd != loop->async_io_watcher.fd)
|
||||
uv__close(loop->async_wfd);
|
||||
loop->async_wfd = -1;
|
||||
}
|
||||
|
||||
uv__io_stop(loop, &loop->async_io_watcher, POLLIN);
|
||||
uv__close(loop->async_io_watcher.fd);
|
||||
loop->async_io_watcher.fd = -1;
|
||||
|
||||
return uv__async_start(loop);
|
||||
}
|
||||
|
||||
|
||||
static void uv__cpu_relax(void) {
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
__asm__ __volatile__ ("rep; nop" ::: "memory"); /* a.k.a. PAUSE */
|
||||
#elif (defined(__arm__) && __ARM_ARCH >= 7) || defined(__aarch64__)
|
||||
__asm__ __volatile__ ("yield" ::: "memory");
|
||||
#elif (defined(__ppc__) || defined(__ppc64__)) && defined(__APPLE__)
|
||||
__asm volatile ("" : : : "memory");
|
||||
#elif !defined(__APPLE__) && (defined(__powerpc64__) || defined(__ppc64__) || defined(__PPC64__))
|
||||
__asm__ __volatile__ ("or 1,1,1; or 2,2,2" ::: "memory");
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -1,63 +0,0 @@
|
||||
/* Copyright (c) 2013, Ben Noordhuis <info@bnoordhuis.nl>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef UV_ATOMIC_OPS_H_
|
||||
#define UV_ATOMIC_OPS_H_
|
||||
|
||||
#include "internal.h" /* UV_UNUSED */
|
||||
|
||||
#if defined(__SUNPRO_C) || defined(__SUNPRO_CC)
|
||||
#include <atomic.h>
|
||||
#endif
|
||||
|
||||
UV_UNUSED(static int cmpxchgi(int* ptr, int oldval, int newval));
|
||||
UV_UNUSED(static void cpu_relax(void));
|
||||
|
||||
/* Prefer hand-rolled assembly over the gcc builtins because the latter also
|
||||
* issue full memory barriers.
|
||||
*/
|
||||
UV_UNUSED(static int cmpxchgi(int* ptr, int oldval, int newval)) {
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
int out;
|
||||
__asm__ __volatile__ ("lock; cmpxchg %2, %1;"
|
||||
: "=a" (out), "+m" (*(volatile int*) ptr)
|
||||
: "r" (newval), "0" (oldval)
|
||||
: "memory");
|
||||
return out;
|
||||
#elif defined(__MVS__)
|
||||
unsigned int op4;
|
||||
if (__plo_CSST(ptr, (unsigned int*) &oldval, newval,
|
||||
(unsigned int*) ptr, *ptr, &op4))
|
||||
return oldval;
|
||||
else
|
||||
return op4;
|
||||
#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
|
||||
return atomic_cas_uint((uint_t *)ptr, (uint_t)oldval, (uint_t)newval);
|
||||
#else
|
||||
return __sync_val_compare_and_swap(ptr, oldval, newval);
|
||||
#endif
|
||||
}
|
||||
|
||||
UV_UNUSED(static void cpu_relax(void)) {
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
__asm__ __volatile__ ("rep; nop" ::: "memory"); /* a.k.a. PAUSE */
|
||||
#elif (defined(__arm__) && __ARM_ARCH >= 7) || defined(__aarch64__)
|
||||
__asm__ __volatile__ ("yield" ::: "memory");
|
||||
#elif defined(__powerpc64__) || defined(__ppc64__) || defined(__PPC64__)
|
||||
__asm__ __volatile__ ("or 1,1,1; or 2,2,2" ::: "memory");
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* UV_ATOMIC_OPS_H_ */
|
||||
@ -27,7 +27,7 @@
|
||||
|
||||
#include <ifaddrs.h>
|
||||
#include <net/if.h>
|
||||
#if !defined(__CYGWIN__) && !defined(__MSYS__)
|
||||
#if !defined(__CYGWIN__) && !defined(__MSYS__) && !defined(__GNU__)
|
||||
#include <net/if_dl.h>
|
||||
#endif
|
||||
|
||||
@ -40,7 +40,7 @@ static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) {
|
||||
return 1;
|
||||
if (ent->ifa_addr == NULL)
|
||||
return 1;
|
||||
#if !defined(__CYGWIN__) && !defined(__MSYS__)
|
||||
#if !defined(__CYGWIN__) && !defined(__MSYS__) && !defined(__GNU__)
|
||||
/*
|
||||
* If `exclude_type` is `UV__EXCLUDE_IFPHYS`, return whether `sa_family`
|
||||
* equals `AF_LINK`. Otherwise, the result depends on the operating
|
||||
@ -65,13 +65,13 @@ static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* TODO(bnoordhuis) share with linux.c */
|
||||
int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
|
||||
uv_interface_address_t* address;
|
||||
struct ifaddrs* addrs;
|
||||
struct ifaddrs* ent;
|
||||
uv_interface_address_t* address;
|
||||
#if !(defined(__CYGWIN__) || defined(__MSYS__))
|
||||
int i;
|
||||
#endif
|
||||
size_t namelen;
|
||||
char* name;
|
||||
|
||||
*count = 0;
|
||||
*addresses = NULL;
|
||||
@ -80,9 +80,11 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
|
||||
return UV__ERR(errno);
|
||||
|
||||
/* Count the number of interfaces */
|
||||
namelen = 0;
|
||||
for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
|
||||
if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFADDR))
|
||||
continue;
|
||||
namelen += strlen(ent->ifa_name) + 1;
|
||||
(*count)++;
|
||||
}
|
||||
|
||||
@ -92,20 +94,22 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
|
||||
}
|
||||
|
||||
/* Make sure the memory is initiallized to zero using calloc() */
|
||||
*addresses = uv__calloc(*count, sizeof(**addresses));
|
||||
|
||||
*addresses = uv__calloc(1, *count * sizeof(**addresses) + namelen);
|
||||
if (*addresses == NULL) {
|
||||
freeifaddrs(addrs);
|
||||
return UV_ENOMEM;
|
||||
}
|
||||
|
||||
name = (char*) &(*addresses)[*count];
|
||||
address = *addresses;
|
||||
|
||||
for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
|
||||
if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFADDR))
|
||||
continue;
|
||||
|
||||
address->name = uv__strdup(ent->ifa_name);
|
||||
namelen = strlen(ent->ifa_name) + 1;
|
||||
address->name = memcpy(name, ent->ifa_name, namelen);
|
||||
name += namelen;
|
||||
|
||||
if (ent->ifa_addr->sa_family == AF_INET6) {
|
||||
address->address.address6 = *((struct sockaddr_in6*) ent->ifa_addr);
|
||||
@ -126,9 +130,11 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
|
||||
address++;
|
||||
}
|
||||
|
||||
#if !(defined(__CYGWIN__) || defined(__MSYS__))
|
||||
#if !(defined(__CYGWIN__) || defined(__MSYS__)) && !defined(__GNU__)
|
||||
/* Fill in physical addresses for each interface */
|
||||
for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
|
||||
int i;
|
||||
|
||||
if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFPHYS))
|
||||
continue;
|
||||
|
||||
@ -151,13 +157,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
|
||||
}
|
||||
|
||||
|
||||
/* TODO(bnoordhuis) share with linux.c */
|
||||
void uv_free_interface_addresses(uv_interface_address_t* addresses,
|
||||
int count) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
uv__free(addresses[i].name);
|
||||
}
|
||||
|
||||
uv__free(addresses);
|
||||
}
|
||||
|
||||
@ -38,6 +38,7 @@ static void init_process_title_mutex_once(void) {
|
||||
|
||||
|
||||
void uv__process_title_cleanup(void) {
|
||||
uv_once(&process_title_mutex_once, init_process_title_mutex_once);
|
||||
uv_mutex_destroy(&process_title_mutex);
|
||||
}
|
||||
|
||||
|
||||
789
src/unix/core.c
789
src/unix/core.c
File diff suppressed because it is too large
Load Diff
@ -36,9 +36,45 @@ int uv_uptime(double* uptime) {
|
||||
}
|
||||
|
||||
int uv_resident_set_memory(size_t* rss) {
|
||||
/* FIXME: read /proc/meminfo? */
|
||||
*rss = 0;
|
||||
char buf[1024];
|
||||
const char* s;
|
||||
long val;
|
||||
int rc;
|
||||
int i;
|
||||
struct sysinfo si;
|
||||
|
||||
/* rss: 24th element */
|
||||
rc = uv__slurp("/proc/self/stat", buf, sizeof(buf));
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
/* find the last ')' */
|
||||
s = strrchr(buf, ')');
|
||||
if (s == NULL)
|
||||
goto err;
|
||||
|
||||
for (i = 1; i <= 22; i++) {
|
||||
s = strchr(s + 1, ' ');
|
||||
if (s == NULL)
|
||||
goto err;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
val = strtol(s, NULL, 10);
|
||||
if (val < 0 || errno != 0)
|
||||
goto err;
|
||||
|
||||
do
|
||||
rc = sysinfo(&si);
|
||||
while (rc == -1 && errno == EINTR);
|
||||
if (rc == -1)
|
||||
return UV__ERR(errno);
|
||||
|
||||
*rss = val * si.mem_unit;
|
||||
return 0;
|
||||
|
||||
err:
|
||||
return UV_EINVAL;
|
||||
}
|
||||
|
||||
int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
|
||||
@ -51,3 +87,7 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
|
||||
uint64_t uv_get_constrained_memory(void) {
|
||||
return 0; /* Memory constraints are unknown. */
|
||||
}
|
||||
|
||||
uint64_t uv_get_available_memory(void) {
|
||||
return uv_get_free_memory();
|
||||
}
|
||||
|
||||
@ -33,25 +33,9 @@
|
||||
#include "darwin-stub.h"
|
||||
#endif
|
||||
|
||||
|
||||
static int uv__pthread_setname_np(const char* name) {
|
||||
char namebuf[64]; /* MAXTHREADNAMESIZE */
|
||||
int err;
|
||||
|
||||
strncpy(namebuf, name, sizeof(namebuf) - 1);
|
||||
namebuf[sizeof(namebuf) - 1] = '\0';
|
||||
|
||||
err = pthread_setname_np(namebuf);
|
||||
if (err)
|
||||
return UV__ERR(err);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int uv__set_process_title(const char* title) {
|
||||
#if TARGET_OS_IPHONE
|
||||
return uv__pthread_setname_np(title);
|
||||
return uv__thread_setname(title);
|
||||
#else
|
||||
CFStringRef (*pCFStringCreateWithCString)(CFAllocatorRef,
|
||||
const char*,
|
||||
@ -177,7 +161,7 @@ int uv__set_process_title(const char* title) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
uv__pthread_setname_np(title); /* Don't care if it fails. */
|
||||
uv__thread_setname(title); /* Don't care if it fails. */
|
||||
err = 0;
|
||||
|
||||
out:
|
||||
|
||||
@ -27,7 +27,6 @@
|
||||
struct CFArrayCallBacks;
|
||||
struct CFRunLoopSourceContext;
|
||||
struct FSEventStreamContext;
|
||||
struct CFRange;
|
||||
|
||||
typedef double CFAbsoluteTime;
|
||||
typedef double CFTimeInterval;
|
||||
@ -43,23 +42,13 @@ typedef unsigned CFStringEncoding;
|
||||
typedef void* CFAllocatorRef;
|
||||
typedef void* CFArrayRef;
|
||||
typedef void* CFBundleRef;
|
||||
typedef void* CFDataRef;
|
||||
typedef void* CFDictionaryRef;
|
||||
typedef void* CFMutableDictionaryRef;
|
||||
typedef struct CFRange CFRange;
|
||||
typedef void* CFRunLoopRef;
|
||||
typedef void* CFRunLoopSourceRef;
|
||||
typedef void* CFStringRef;
|
||||
typedef void* CFTypeRef;
|
||||
typedef void* FSEventStreamRef;
|
||||
|
||||
typedef uint32_t IOOptionBits;
|
||||
typedef unsigned int io_iterator_t;
|
||||
typedef unsigned int io_object_t;
|
||||
typedef unsigned int io_service_t;
|
||||
typedef unsigned int io_registry_entry_t;
|
||||
|
||||
|
||||
typedef void (*FSEventStreamCallback)(const FSEventStreamRef,
|
||||
void*,
|
||||
size_t,
|
||||
@ -80,11 +69,6 @@ struct FSEventStreamContext {
|
||||
void* pad[3];
|
||||
};
|
||||
|
||||
struct CFRange {
|
||||
CFIndex location;
|
||||
CFIndex length;
|
||||
};
|
||||
|
||||
static const CFStringEncoding kCFStringEncodingUTF8 = 0x8000100;
|
||||
static const OSStatus noErr = 0;
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user