<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body><p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">Here is an updated job with easier to read comments:</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;"><a href="https://testbot.winehq.org/JobDetails.pl?Key=97235">https://testbot.winehq.org/JobDetails.pl?Key=97235</a></p>
<br /><p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">Le jeudi 2 septembre 2021, 19:08:43 CEST Guillaume Charifi-Hoareau a écrit :</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> Thank you for your answer!</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> </p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> </p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> I spent a lot of time testing a whole lot of different combinations and the</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> results still confused me...</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> </p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> > There's also a part of me that would like to know what can possibly be</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> > the point of this API; it's hard to even think of what "reasonable"</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> > behaviour is otherwise. Do you happen to know?</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> > </p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> > My best guess is that it's meant to explicitly interrupt poll requests</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> > somehow (what, I/O cancellation wasn't good enough for them?), in which</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> > case it'd be good to explicitly confirm or refute that the "exclusive"</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> > poll really does act like a normal poll, and doesn't e.g. return</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> > immediately.</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> </p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> I discovered this behavior while investigating an app that seemed to rely on</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> them to interrupt some polls, and so far it seems to be its sole purpose.</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> There is only one reason I can imagine a use for this instead of CancelIo():</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> As the NtDeviceIoControlFile()'s file handle is independent of the socket</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> in params, it provides a way to interrupt another poll that waits on the</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> same socket without the need to know the file handle that was originally</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> given to it.</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> </p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> Regardless its behaviour is kind of crazy.</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> I tried to restrict to a subset of the tests to avoid polluting test_poll()</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> too much, but indeed it requires an entire function to test it properly.</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> </p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> > I think these tests could be more extensive. For example:</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> > </p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> > * What happens if you try to perform a non-exclusive wait while an</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> > exclusive wait is in progress? i.e. the inverse of the test added here.</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> </p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> So after some extensive testing, I'm rather confident that the logic for a</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> new poll on a socket is:</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> (The main poll is an arbitrary designation for one of the poll waiting on</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> the socket) If there is no main poll on the socket, then the new poll</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> becomes the main poll. If the main poll is terminated, then there is no</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> main poll anymore. If the main poll is exclusive and the new poll is</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> exclusive, then the main poll is terminated and the new poll becomes the</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> main poll.</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> </p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> </p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> The flag does not seem to do anything more than this (apart from requiring</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> 0x7fffffff00000000 <= timeout <= 0x7fffffffffffffff).</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> </p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> > * Can we verify that exclusive waits are specific to a given socket</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> > (i.e. you can simultaneously do an exclusive wait on two different</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> > sockets?)</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> Yes, the mechanism described earlier seems to be done on a per-socket basis.</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> > * Can we test that exclusive waits apply if two unequal sets overlap?</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> </p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> Yes, it works the same way (a single common socket between exclusive polls</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> is enough to wake the poll)</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> </p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> > * Can you do an exclusive wait on the same socket from two different</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> > threads?</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> </p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> Can yes, didn't want to, but did it anyway :)</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> I get the expected result: It works exactly the same as the single threaded</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> version.</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> </p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> So I guess I now have enough insight to write a proper implementation.</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> The patch for the tests is attached to this job:</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> https://testbot.winehq.org/JobDetails.pl? Key=97234[1]</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> Feel free to tell me if other tests come to your mind.</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> </p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> Le mercredi 1 septembre 2021, 17:52:14 CEST Guillaume Charifi a écrit :</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> > Signed-off-by: Guillaume Charifi <guillaume.charifi@sfr.fr></p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> > ---</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> > </p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> >  dlls/ws2_32/tests/afd.c | 73 ++++++++++++++++++++++++++++++++++++++++-</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> >  1 file changed, 72 insertions(+), 1 deletion(-)</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> > </p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> > diff --git a/dlls/ws2_32/tests/afd.c b/dlls/ws2_32/tests/afd.c</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> > index eb7c8ee50de..2568f251b6f 100644</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> > --- a/dlls/ws2_32/tests/afd.c</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> > +++ b/dlls/ws2_32/tests/afd.c</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> > @@ -148,8 +148,10 @@ static void test_poll(void)</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> > </p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> >      const struct sockaddr_in bind_addr = {.sin_family = AF_INET,</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> > </p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> > .sin_addr.s_addr = htonl(INADDR_LOOPBACK)}; char in_buffer[offsetof(struct</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> > afd_poll_params, sockets[3])]; char out_buffer[offsetof(struct</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> > afd_poll_params, sockets[3])]; +    char out_buffer1[offsetof(struct</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> > afd_poll_params, sockets[3])]; struct afd_poll_params *in_params = (struct</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> > afd_poll_params *)in_buffer; struct afd_poll_params *out_params = (struct</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> > afd_poll_params *)out_buffer; +    struct afd_poll_params *out_params1 =</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> > (struct afd_poll_params *)out_buffer1; int large_buffer_size = 1024 *</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> > 1024;</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> > </p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> >      SOCKET client, server, listener;</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> >      struct sockaddr_in addr;</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> > </p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> > @@ -157,13 +159,14 @@ static void test_poll(void)</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> > </p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> >      IO_STATUS_BLOCK io;</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> >      LARGE_INTEGER now;</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> >      ULONG params_size;</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> > </p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> > -    HANDLE event;</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> > +    HANDLE event, event1;</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> > </p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> >      int ret, len;</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> >      </p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> >      large_buffer = malloc(large_buffer_size);</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> >      memset(in_buffer, 0, sizeof(in_buffer));</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> >      memset(out_buffer, 0, sizeof(out_buffer));</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> >      event = CreateEventW(NULL, TRUE, FALSE, NULL);</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> > </p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> > +    event1 = CreateEventW(NULL, TRUE, FALSE, NULL);</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> > </p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> >      listener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> >      ret = bind(listener, (const struct sockaddr *)&bind_addr,</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> > </p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> > sizeof(bind_addr)); @@ -208,10 +211,77 @@ static void test_poll(void)</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> > </p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> >              IOCTL_AFD_POLL, in_params, params_size, out_params,</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> > </p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> > params_size); ok(ret == STATUS_INVALID_PARAMETER, "got %#x\n", ret);</p>
<br /><br /></body>
</html>