Re: [PATCH] error handling: Use TFR() macro where applicable

2022-10-10 Thread Peter Maydell
On Mon, 10 Oct 2022 at 09:34, Nikita Ivanov  wrote:
>
> Hi! Thanks for your notes. I'll try to send updated patches by the end of the 
> day.
>
> On Fri, Oct 7, 2022 at 6:32 PM Peter Maydell  wrote:
>> I'm not sure why you've put the TEMP_FAILURE_RETRY on the outside here
>> rather than just on the individual function calls.
>
>
> The original code contained both branches in one while loop, so I was afraid 
> that
> value `aiocb->aio_type & QEMU_AIO_WRITE` would change somehow during the loop.
> If you'll say that this is impossible, I'll adjust the code as you propose.

Oh, yes, I see. No, nothing should be changing that during the loop,
I think it's just written the way it is now because it seemed neater
when you write out the retry longhand.

-- PMM



Re: [PATCH] error handling: Use TFR() macro where applicable

2022-10-10 Thread Nikita Ivanov
Hi! Thanks for your notes. I'll try to send updated patches by the end of
the day.

On Fri, Oct 7, 2022 at 6:32 PM Peter Maydell 
wrote:

> I think this patch is doing things in the wrong order. Instead of
> converting code to use the old macro that we don't like and then
> updating it again in patch 2 to use the new macro, we should
> first introduce the new macro, and then after that we can update
> code that's currently not using a macro at all to use the new one.
> This makes code review easier because we don't have to look at a
> change to this code which is then going to be rewritten anyway.


Sounds smooth. I'll refactor patches accordingly.


> >  if (ret < 0) {
> >  ret = -errno;
>
>
> > @@ -1472,8 +1472,8 @@ static ssize_t
> handle_aiocb_rw_vector(RawPosixAIOData *aiocb)
> >  {
> >  ssize_t len;
> >
> > -TFR(
> > -len = (aiocb->aio_type & QEMU_AIO_WRITE) ?
> > +len = TEMP_FAILURE_RETRY(
> > +(aiocb->aio_type & QEMU_AIO_WRITE) ?
> >  qemu_pwritev(aiocb->aio_fildes,
> > aiocb->io.iov,
> > aiocb->io.niov,
>
> I'm not sure why you've put the TEMP_FAILURE_RETRY on the outside here
> rather than just on the individual function calls.
>

The original code contained both branches in one while loop, so I was
afraid that
value `aiocb->aio_type & QEMU_AIO_WRITE` would change somehow during the
loop.
If you'll say that this is impossible, I'll adjust the code as you propose.

> diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h
> > index b1c161c035..6e244f15fa 100644
> > --- a/include/qemu/osdep.h
> > +++ b/include/qemu/osdep.h
> > @@ -243,7 +243,13 @@ void QEMU_ERROR("code path is reachable")
> >  #define ESHUTDOWN 4099
> >  #endif
> >
> > -#define TFR(expr) do { if ((expr) != -1) break; } while (errno == EINTR)
> > +#define TEMP_FAILURE_RETRY(expr) \
>
> We can't call the macro this, because the glibc system headers already
> may define a macro of that name, so the compiler will complain if they're
> both defined at the same time, and depending on header ordering it might
> not be clear which version you're getting.
>

Sorry, my fault. I will rename it to "RETRY_ON_EINTR" as it was proposed
earlier in this thread.
-- 
Best Regards,
*Nikita Ivanov* | C developer


Re: [PATCH] error handling: Use TFR() macro where applicable

2022-10-07 Thread Peter Maydell
On Fri, 7 Oct 2022 at 12:44, Nikita Ivanov  wrote:
>
> Hi!
> Sorry for such a long absence, I've been resolving some other issues in my 
> life for a while. I've adjusted the patch according to your latest comments. 
> Could you check it out, please?

Hi; thanks for coming back to this. (I'd been meaning to re-read the
thread but hadn't found time to do so; sorry.) As Christian says,
you should send the patches as a proper new patchset thread of their
own, but for the moment:

> From 5389c5ccc8789f8f666ab99e50d38af728bd2c9c Mon Sep 17 00:00:00 2001
> From: Nikita Ivanov 
> Date: Wed, 3 Aug 2022 12:54:00 +0300
> Subject: [PATCH 1/2] error handling: Use TFR() macro where applicable
>
> There is a defined TFR() macro in qemu/osdep.h which
> handles the same while loop.
> Resolves: https://gitlab.com/qemu-project/qemu/-/issues/415
>
> Signed-off-by: Nikita Ivanov 

> diff --git a/block/file-posix.c b/block/file-posix.c
> index 66fdb07820..7892bdea31 100644
> --- a/block/file-posix.c
> +++ b/block/file-posix.c
> @@ -1238,9 +1238,9 @@ static int hdev_get_max_segments(int fd, struct stat 
> *st)
>  ret = -errno;
>  goto out;
>  }
> -do {
> -ret = read(sysfd, buf, sizeof(buf) - 1);
> -} while (ret == -1 && errno == EINTR);
> +TFR(
> +ret = read(sysfd, buf, sizeof(buf) - 1)
> +);

I think this patch is doing things in the wrong order. Instead of
converting code to use the old macro that we don't like and then
updating it again in patch 2 to use the new macro, we should
first introduce the new macro, and then after that we can update
code that's currently not using a macro at all to use the new one.
This makes code review easier because we don't have to look at a
change to this code which is then going to be rewritten anyway.


> From 7a9fccf00ec2d1c6b30b2ed1cb98398b49ddb0bc Mon Sep 17 00:00:00 2001
> From: Nikita Ivanov 
> Date: Mon, 8 Aug 2022 20:43:45 +0300
> Subject: [PATCH 2/2] Refactoring: rename TFR() to TEMP_FAILURE_RETRY()
>
> glibc's unistd.h header provides the same macro with the
> subtle difference in type casting. Adjust macro name to the
> common standard and refactor it to expression.
>
> Signed-off-by: Nikita Ivanov 


> diff --git a/block/file-posix.c b/block/file-posix.c
> index 7892bdea31..ee7f60c78a 100644
> --- a/block/file-posix.c
> +++ b/block/file-posix.c
> @@ -1238,8 +1238,8 @@ static int hdev_get_max_segments(int fd, struct stat 
> *st)
>  ret = -errno;
>  goto out;
>  }
> -TFR(
> -ret = read(sysfd, buf, sizeof(buf) - 1)
> +ret = TEMP_FAILURE_RETRY(
> +read(sysfd, buf, sizeof(buf) - 1)
>  );

This doesn't need these newlines in it. If the whole thing fits on
a single line, that's easier to read.

>  if (ret < 0) {
>  ret = -errno;


> @@ -1472,8 +1472,8 @@ static ssize_t handle_aiocb_rw_vector(RawPosixAIOData 
> *aiocb)
>  {
>  ssize_t len;
>
> -TFR(
> -len = (aiocb->aio_type & QEMU_AIO_WRITE) ?
> +len = TEMP_FAILURE_RETRY(
> +(aiocb->aio_type & QEMU_AIO_WRITE) ?
>  qemu_pwritev(aiocb->aio_fildes,
> aiocb->io.iov,
> aiocb->io.niov,

I'm not sure why you've put the TEMP_FAILURE_RETRY on the outside here
rather than just on the individual function calls.


> diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h
> index b1c161c035..6e244f15fa 100644
> --- a/include/qemu/osdep.h
> +++ b/include/qemu/osdep.h
> @@ -243,7 +243,13 @@ void QEMU_ERROR("code path is reachable")
>  #define ESHUTDOWN 4099
>  #endif
>
> -#define TFR(expr) do { if ((expr) != -1) break; } while (errno == EINTR)
> +#define TEMP_FAILURE_RETRY(expr) \

We can't call the macro this, because the glibc system headers already
may define a macro of that name, so the compiler will complain if they're
both defined at the same time, and depending on header ordering it might
not be clear which version you're getting.

> +(__extension__  \
> +({ typeof(int64_t) __result;   \

As Christian says, the point of the typeof is to use the type
of the expression. "typeof(int64_t)" is always just "int64_t".
You want "typeof(expr) __result;".

> +   do { \
> +__result = (typeof(int64_t)) (expression); \

Then you don't need this cast, because both __result and expr
are the same type anyway.

Also, how did this compile? 'expression' isn't the name of the macro argument.

> +   } while (__result == -1L && errno == EINTR); \

I think you don't need the 'L' suffix here.

> +   __result; }))

thanks
-- PMM



Re: [PATCH] error handling: Use TFR() macro where applicable

2022-10-07 Thread Christian Schoenebeck
On Freitag, 7. Oktober 2022 13:44:28 CEST Nikita Ivanov wrote:
> Hi!

Hi Nikita!

> Sorry for such a long absence, I've been resolving some other issues in my
> life for a while. I've adjusted the patch according to your latest
> comments. Could you check it out, please?

Sorry for the drill, but I fear this has to follow common form for patch 
submissions:

  * one email as cover letter

  * two (additional) separate emails for the two patches, each referencing the 
cover letter email

  * bumping the version in subject line

https://www.qemu.org/docs/master/devel/submitting-a-patch.html

One more comment on patch 2 below ...

> From 5389c5ccc8789f8f666ab99e50d38af728bd2c9c Mon Sep 17 00:00:00 2001
> From: Nikita Ivanov 
> Date: Wed, 3 Aug 2022 12:54:00 +0300
> Subject: [PATCH 1/2] error handling: Use TFR() macro where applicable
> 
> There is a defined TFR() macro in qemu/osdep.h which
> handles the same while loop.
> Resolves: https://gitlab.com/qemu-project/qemu/-/issues/415
> 
> Signed-off-by: Nikita Ivanov 
> ---
>  block/file-posix.c| 39 ++-
>  chardev/char-pty.c|  4 +---
>  hw/9pfs/9p-local.c|  8 ++--
>  net/l2tpv3.c  | 15 +++
>  net/socket.c  | 16 +++-
>  net/tap.c |  8 ++--
>  qga/commands-posix.c  |  4 +---
>  semihosting/syscalls.c|  4 +---
>  tests/qtest/libqtest.c| 14 +++---
>  tests/vhost-user-bridge.c |  4 +---
>  util/main-loop.c  |  4 +---
>  util/osdep.c  |  4 +---
>  util/vfio-helpers.c   | 12 ++--
>  13 files changed, 51 insertions(+), 85 deletions(-)
> 
> diff --git a/block/file-posix.c b/block/file-posix.c
> index 66fdb07820..7892bdea31 100644
> --- a/block/file-posix.c
> +++ b/block/file-posix.c
> @@ -1238,9 +1238,9 @@ static int hdev_get_max_segments(int fd, struct stat
> *st)
>  ret = -errno;
>  goto out;
>  }
> -do {
> -ret = read(sysfd, buf, sizeof(buf) - 1);
> -} while (ret == -1 && errno == EINTR);
> +TFR(
> +ret = read(sysfd, buf, sizeof(buf) - 1)
> +);
>  if (ret < 0) {
>  ret = -errno;
>  goto out;
> @@ -1388,9 +1388,9 @@ static int handle_aiocb_ioctl(void *opaque)
>  RawPosixAIOData *aiocb = opaque;
>  int ret;
> 
> -do {
> -ret = ioctl(aiocb->aio_fildes, aiocb->ioctl.cmd, aiocb->ioctl.buf);
> -} while (ret == -1 && errno == EINTR);
> +TFR(
> +ret = ioctl(aiocb->aio_fildes, aiocb->ioctl.cmd, aiocb->ioctl.buf)
> +);
>  if (ret == -1) {
>  return -errno;
>  }
> @@ -1472,18 +1472,17 @@ static ssize_t
> handle_aiocb_rw_vector(RawPosixAIOData *aiocb)
>  {
>  ssize_t len;
> 
> -do {
> -if (aiocb->aio_type & QEMU_AIO_WRITE)
> -len = qemu_pwritev(aiocb->aio_fildes,
> -   aiocb->io.iov,
> -   aiocb->io.niov,
> -   aiocb->aio_offset);
> - else
> -len = qemu_preadv(aiocb->aio_fildes,
> -  aiocb->io.iov,
> -  aiocb->io.niov,
> -  aiocb->aio_offset);
> -} while (len == -1 && errno == EINTR);
> +TFR(
> +len = (aiocb->aio_type & QEMU_AIO_WRITE) ?
> +qemu_pwritev(aiocb->aio_fildes,
> +   aiocb->io.iov,
> +   aiocb->io.niov,
> +   aiocb->aio_offset) :
> +qemu_preadv(aiocb->aio_fildes,
> +  aiocb->io.iov,
> +  aiocb->io.niov,
> +  aiocb->aio_offset)
> +);
> 
>  if (len == -1) {
>  return -errno;
> @@ -1908,9 +1907,7 @@ static int allocate_first_block(int fd, size_t
> max_size)
>  buf = qemu_memalign(max_align, write_size);
>  memset(buf, 0, write_size);
> 
> -do {
> -n = pwrite(fd, buf, write_size, 0);
> -} while (n == -1 && errno == EINTR);
> +TFR(n = pwrite(fd, buf, write_size, 0));
> 
>  ret = (n == -1) ? -errno : 0;
> 
> diff --git a/chardev/char-pty.c b/chardev/char-pty.c
> index 53f25c6bbd..b2f490bacf 100644
> --- a/chardev/char-pty.c
> +++ b/chardev/char-pty.c
> @@ -93,9 +93,7 @@ static void pty_chr_update_read_handler(Chardev *chr)
>  pfd.fd = fioc->fd;
>  pfd.events = G_IO_OUT;
>  pfd.revents = 0;
> -do {
> -rc = g_poll(, 1, 0);
> -} while (rc == -1 && errno == EINTR);
> +TFR(rc = g_poll(, 1, 0));
>  assert(rc >= 0);
> 
>  if (pfd.revents & G_IO_HUP) {
> diff --git a/hw/9pfs/9p-local.c b/hw/9pfs/9p-local.c
> index d42ce6d8b8..c90ab947ba 100644
> --- a/hw/9pfs/9p-local.c
> +++ b/hw/9pfs/9p-local.c
> @@ -470,9 +470,7 @@ static ssize_t local_readlink(FsContext *fs_ctx,
> V9fsPath *fs_path,
>  if (fd == -1) {
>  return -1;
>  }
> -do {
> -tsize = 

Re: [PATCH] error handling: Use TFR() macro where applicable

2022-10-07 Thread Nikita Ivanov
Hi!
Sorry for such a long absence, I've been resolving some other issues in my
life for a while. I've adjusted the patch according to your latest
comments. Could you check it out, please?

>From 5389c5ccc8789f8f666ab99e50d38af728bd2c9c Mon Sep 17 00:00:00 2001
From: Nikita Ivanov 
Date: Wed, 3 Aug 2022 12:54:00 +0300
Subject: [PATCH 1/2] error handling: Use TFR() macro where applicable

There is a defined TFR() macro in qemu/osdep.h which
handles the same while loop.
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/415

Signed-off-by: Nikita Ivanov 
---
 block/file-posix.c| 39 ++-
 chardev/char-pty.c|  4 +---
 hw/9pfs/9p-local.c|  8 ++--
 net/l2tpv3.c  | 15 +++
 net/socket.c  | 16 +++-
 net/tap.c |  8 ++--
 qga/commands-posix.c  |  4 +---
 semihosting/syscalls.c|  4 +---
 tests/qtest/libqtest.c| 14 +++---
 tests/vhost-user-bridge.c |  4 +---
 util/main-loop.c  |  4 +---
 util/osdep.c  |  4 +---
 util/vfio-helpers.c   | 12 ++--
 13 files changed, 51 insertions(+), 85 deletions(-)

diff --git a/block/file-posix.c b/block/file-posix.c
index 66fdb07820..7892bdea31 100644
--- a/block/file-posix.c
+++ b/block/file-posix.c
@@ -1238,9 +1238,9 @@ static int hdev_get_max_segments(int fd, struct stat
*st)
 ret = -errno;
 goto out;
 }
-do {
-ret = read(sysfd, buf, sizeof(buf) - 1);
-} while (ret == -1 && errno == EINTR);
+TFR(
+ret = read(sysfd, buf, sizeof(buf) - 1)
+);
 if (ret < 0) {
 ret = -errno;
 goto out;
@@ -1388,9 +1388,9 @@ static int handle_aiocb_ioctl(void *opaque)
 RawPosixAIOData *aiocb = opaque;
 int ret;

-do {
-ret = ioctl(aiocb->aio_fildes, aiocb->ioctl.cmd, aiocb->ioctl.buf);
-} while (ret == -1 && errno == EINTR);
+TFR(
+ret = ioctl(aiocb->aio_fildes, aiocb->ioctl.cmd, aiocb->ioctl.buf)
+);
 if (ret == -1) {
 return -errno;
 }
@@ -1472,18 +1472,17 @@ static ssize_t
handle_aiocb_rw_vector(RawPosixAIOData *aiocb)
 {
 ssize_t len;

-do {
-if (aiocb->aio_type & QEMU_AIO_WRITE)
-len = qemu_pwritev(aiocb->aio_fildes,
-   aiocb->io.iov,
-   aiocb->io.niov,
-   aiocb->aio_offset);
- else
-len = qemu_preadv(aiocb->aio_fildes,
-  aiocb->io.iov,
-  aiocb->io.niov,
-  aiocb->aio_offset);
-} while (len == -1 && errno == EINTR);
+TFR(
+len = (aiocb->aio_type & QEMU_AIO_WRITE) ?
+qemu_pwritev(aiocb->aio_fildes,
+   aiocb->io.iov,
+   aiocb->io.niov,
+   aiocb->aio_offset) :
+qemu_preadv(aiocb->aio_fildes,
+  aiocb->io.iov,
+  aiocb->io.niov,
+  aiocb->aio_offset)
+);

 if (len == -1) {
 return -errno;
@@ -1908,9 +1907,7 @@ static int allocate_first_block(int fd, size_t
max_size)
 buf = qemu_memalign(max_align, write_size);
 memset(buf, 0, write_size);

-do {
-n = pwrite(fd, buf, write_size, 0);
-} while (n == -1 && errno == EINTR);
+TFR(n = pwrite(fd, buf, write_size, 0));

 ret = (n == -1) ? -errno : 0;

diff --git a/chardev/char-pty.c b/chardev/char-pty.c
index 53f25c6bbd..b2f490bacf 100644
--- a/chardev/char-pty.c
+++ b/chardev/char-pty.c
@@ -93,9 +93,7 @@ static void pty_chr_update_read_handler(Chardev *chr)
 pfd.fd = fioc->fd;
 pfd.events = G_IO_OUT;
 pfd.revents = 0;
-do {
-rc = g_poll(, 1, 0);
-} while (rc == -1 && errno == EINTR);
+TFR(rc = g_poll(, 1, 0));
 assert(rc >= 0);

 if (pfd.revents & G_IO_HUP) {
diff --git a/hw/9pfs/9p-local.c b/hw/9pfs/9p-local.c
index d42ce6d8b8..c90ab947ba 100644
--- a/hw/9pfs/9p-local.c
+++ b/hw/9pfs/9p-local.c
@@ -470,9 +470,7 @@ static ssize_t local_readlink(FsContext *fs_ctx,
V9fsPath *fs_path,
 if (fd == -1) {
 return -1;
 }
-do {
-tsize = read(fd, (void *)buf, bufsz);
-} while (tsize == -1 && errno == EINTR);
+TFR(tsize = read(fd, (void *)buf, bufsz));
 close_preserve_errno(fd);
 } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
(fs_ctx->export_flags & V9FS_SM_NONE)) {
@@ -908,9 +906,7 @@ static int local_symlink(FsContext *fs_ctx, const char
*oldpath,
 }
 /* Write the oldpath (target) to the file. */
 oldpath_size = strlen(oldpath);
-do {
-write_size = write(fd, (void *)oldpath, oldpath_size);
-} while (write_size == -1 && errno == EINTR);
+TFR(write_size = write(fd, (void *)oldpath, oldpath_size));
 

Re: [PATCH] error handling: Use TFR() macro where applicable

2022-08-18 Thread Peter Maydell
On Thu, 18 Aug 2022 at 15:07, Christian Schoenebeck
 wrote:
>
> On Mittwoch, 17. August 2022 17:55:24 CEST Peter Maydell wrote:
> > On Wed, 17 Aug 2022 at 15:49, Nikita Ivanov  wrote:
> > > Well...
> > >
> > > What exactly is still under discussion? In my perspective, the main
> > > pitfalls have been resolved:
> > >
> > > 0. All possible places where TFR() macro could be applied are covered.
> > > 1. Macro has been renamed in order to be more transparent. The name has
> > > been chosen in comparison with a similar glibc macro. 2. The macro itself
> > > has been refactored, in order to replace it entirely with glibc
> > > alternative. 3. Problems with statement/expressions differences in qemu
> > > and glibc implementation have been resolved.
> > >
> > > Is there any room for improvement?
> >
> > (a) do we want the statement version or the expression version?
>
> I think the tendency was in favour for the expression version? Markus made it
> clear that the glibc version indeed may evaluate as an expression (GCC
> extension).

Sounds good to me.

> > (b) do we want "use the glibc one, with same-semantics version for
> > compatibility", or do we want "we have our own thing"?
> >
> > I would have voted for following glibc, except that it does
> > that cast-to-long thing, which is incorrect behaviour when
> > long is 32 bits and the return value from the function being
> > tested is 64 bits.
>
> Then simply int64_t as a type instead, and as "our own thing"?

I think this is probably what I would go for, except that we
should use typeof() rather than a specific type.

Then we get to bikeshed the macro name again :-)

-- PMM



Re: [PATCH] error handling: Use TFR() macro where applicable

2022-08-18 Thread Christian Schoenebeck
On Mittwoch, 17. August 2022 17:55:24 CEST Peter Maydell wrote:
> On Wed, 17 Aug 2022 at 15:49, Nikita Ivanov  wrote:
> > Well...
> > 
> > What exactly is still under discussion? In my perspective, the main
> > pitfalls have been resolved:
> > 
> > 0. All possible places where TFR() macro could be applied are covered.
> > 1. Macro has been renamed in order to be more transparent. The name has
> > been chosen in comparison with a similar glibc macro. 2. The macro itself
> > has been refactored, in order to replace it entirely with glibc
> > alternative. 3. Problems with statement/expressions differences in qemu
> > and glibc implementation have been resolved.
> > 
> > Is there any room for improvement?
> 
> (a) do we want the statement version or the expression version?

I think the tendency was in favour for the expression version? Markus made it 
clear that the glibc version indeed may evaluate as an expression (GCC 
extension).

> (b) do we want "use the glibc one, with same-semantics version for
> compatibility", or do we want "we have our own thing"?
> 
> I would have voted for following glibc, except that it does
> that cast-to-long thing, which is incorrect behaviour when
> long is 32 bits and the return value from the function being
> tested is 64 bits.

Then simply int64_t as a type instead, and as "our own thing"?

Best regards,
Christian Schoenebeck





Re: [PATCH] error handling: Use TFR() macro where applicable

2022-08-17 Thread Peter Maydell
On Wed, 17 Aug 2022 at 15:49, Nikita Ivanov  wrote:
>
> Well...
>
> What exactly is still under discussion? In my perspective, the main pitfalls 
> have been resolved:
>
> 0. All possible places where TFR() macro could be applied are covered.
> 1. Macro has been renamed in order to be more transparent. The name has been 
> chosen in comparison with a similar glibc macro.
> 2. The macro itself has been refactored, in order to replace it entirely with 
> glibc alternative.
> 3. Problems with statement/expressions differences in qemu and glibc 
> implementation have been resolved.
>
> Is there any room for improvement?

(a) do we want the statement version or the expression version?
(b) do we want "use the glibc one, with same-semantics version for
compatibility", or do we want "we have our own thing"?

I would have voted for following glibc, except that it does
that cast-to-long thing, which is incorrect behaviour when
long is 32 bits and the return value from the function being
tested is 64 bits.

thanks
-- PMM



Re: [PATCH] error handling: Use TFR() macro where applicable

2022-08-17 Thread Nikita Ivanov
Well...

What exactly is still under discussion? In my perspective, the main
pitfalls have been resolved:

0. All possible places where TFR() macro could be applied are covered.
1. Macro has been renamed in order to be more transparent. The name has
been chosen in comparison with a similar glibc macro.
2. The macro itself has been refactored, in order to replace it entirely
with glibc alternative.
3. Problems with statement/expressions differences in qemu and glibc
implementation have been resolved.

Is there any room for improvement?


On Wed, Aug 17, 2022 at 5:17 PM Peter Maydell 
wrote:

> On Wed, 17 Aug 2022 at 15:06, Nikita Ivanov 
> wrote:
> >
> > Hi! Are there any updates? I have not received any comments since the
> last email.
>
> Looking at the thread, I don't think we (yet) have consensus on the
> right thing to do here...
>
> thanks
> -- PMM
>


-- 
Best Regards,
*Nikita Ivanov* | C developer
*Telephone:* +79140870696
*Telephone:* +79015053149


Re: [PATCH] error handling: Use TFR() macro where applicable

2022-08-17 Thread Peter Maydell
On Wed, 17 Aug 2022 at 15:06, Nikita Ivanov  wrote:
>
> Hi! Are there any updates? I have not received any comments since the last 
> email.

Looking at the thread, I don't think we (yet) have consensus on the
right thing to do here...

thanks
-- PMM



Re: [PATCH] error handling: Use TFR() macro where applicable

2022-08-17 Thread Nikita Ivanov
_required = 0;
>  }
>
> -TFR(fd = tap_open(ifname, ifname_sz, vnet_hdr, vnet_hdr_required,
> -  mq_required, errp));
> +fd = TEMP_FAILURE_RETRY(
> +tap_open(ifname, ifname_sz, vnet_hdr, vnet_hdr_required,
> +  mq_required, errp)
> +);
>  if (fd < 0) {
>  return -1;
>  }
> diff --git a/os-posix.c b/os-posix.c
> index 321fc4bd13..59cac65585 100644
> --- a/os-posix.c
> +++ b/os-posix.c
> @@ -266,7 +266,7 @@ void os_setup_post(void)
>  error_report("not able to chdir to /: %s", strerror(errno));
>  exit(1);
>  }
> -TFR(fd = qemu_open_old("/dev/null", O_RDWR));
> +fd = TEMP_FAILURE_RETRY(qemu_open_old("/dev/null", O_RDWR));
>  if (fd == -1) {
>  exit(1);
>  }
> diff --git a/qga/commands-posix.c b/qga/commands-posix.c
> index 90f83aa9b6..feb0fab807 100644
> --- a/qga/commands-posix.c
> +++ b/qga/commands-posix.c
> @@ -68,7 +68,7 @@ static void ga_wait_child(pid_t pid, int *status, Error
> **errp)
>
>  *status = 0;
>
> -TFR(rpid = waitpid(pid, status, 0));
> +rpid = TEMP_FAILURE_RETRY(waitpid(pid, status, 0));
>
>  if (rpid == -1) {
>  error_setg_errno(errp, errno, "failed to wait for child (pid:
> %d)",
> diff --git a/semihosting/syscalls.c b/semihosting/syscalls.c
> index 025c08147a..0cbef7d22b 100644
> --- a/semihosting/syscalls.c
> +++ b/semihosting/syscalls.c
> @@ -317,7 +317,7 @@ static void host_read(CPUState *cs,
> gdb_syscall_complete_cb complete,
>  complete(cs, -1, EFAULT);
>  return;
>  }
> -TFR(ret = read(gf->hostfd, ptr, len));
> +ret = TEMP_FAILURE_RETRY(read(gf->hostfd, ptr, len));
>  if (ret == -1) {
>  complete(cs, -1, errno);
>  unlock_user(ptr, buf, 0);
> diff --git a/tests/qtest/libqtest.c b/tests/qtest/libqtest.c
> index d4022966b3..4a12824dc4 100644
> --- a/tests/qtest/libqtest.c
> +++ b/tests/qtest/libqtest.c
> @@ -102,8 +102,8 @@ static int socket_accept(int sock)
>  }
>
>  addrlen = sizeof(addr);
> -TFR(
> -ret = accept(sock, (struct sockaddr *), )
> +ret = TEMP_FAILURE_RETRY(
> +accept(sock, (struct sockaddr *), )
>  );
>  if (ret == -1) {
>  fprintf(stderr, "%s failed: %s\n", __func__, strerror(errno));
> @@ -140,7 +140,7 @@ void qtest_kill_qemu(QTestState *s)
>  /* Skip wait if qtest_probe_child already reaped.  */
>  if (pid != -1) {
>  kill(pid, SIGTERM);
> -TFR(pid = waitpid(s->qemu_pid, >wstatus, 0));
> +pid = TEMP_FAILURE_RETRY(waitpid(s->qemu_pid, >wstatus, 0));
>  assert(pid == s->qemu_pid);
>  s->qemu_pid = -1;
>  }
> @@ -578,8 +578,8 @@ int qtest_socket_server(const char *socket_path)
>  addr.sun_family = AF_UNIX;
>  snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", socket_path);
>
> -TFR(
> -ret = bind(sock, (struct sockaddr *), sizeof(addr))
> +ret = TEMP_FAILURE_RETRY(
> +bind(sock, (struct sockaddr *), sizeof(addr))
>  );
>  g_assert_cmpint(ret, !=, -1);
>  ret = listen(sock, 1);
> diff --git a/tests/vhost-user-bridge.c b/tests/vhost-user-bridge.c
> index 4d8f933ed5..624a211f3d 100644
> --- a/tests/vhost-user-bridge.c
> +++ b/tests/vhost-user-bridge.c
> @@ -331,7 +331,9 @@ vubr_backend_recv_cb(int sock, void *ctx)
>  .msg_iovlen = num,
>  .msg_flags = MSG_DONTWAIT,
>  };
> -TFR(ret = recvmsg(vubr->backend_udp_sock, , 0));
> +ret = TEMP_FAILURE_RETRY(
> +recvmsg(vubr->backend_udp_sock, , 0)
> +);
>
>  if (i == 0) {
>  iov_restore_front(elem->in_sg, sg, hdrlen);
> diff --git a/util/main-loop.c b/util/main-loop.c
> index 58e14db2d4..5f65f928bd 100644
> --- a/util/main-loop.c
> +++ b/util/main-loop.c
> @@ -64,7 +64,7 @@ static void sigfd_handler(void *opaque)
>  ssize_t len;
>
>  while (1) {
> -TFR(len = read(fd, , sizeof(info)));
> +len = TEMP_FAILURE_RETRY(read(fd, , sizeof(info)));
>
>  if (len == -1 && errno == EAGAIN) {
>  break;
> diff --git a/util/osdep.c b/util/osdep.c
> index d35c473ac7..2c287e75e7 100644
> --- a/util/osdep.c
> +++ b/util/osdep.c
> @@ -244,7 +244,7 @@ static int qemu_lock_fcntl(int fd, int64_t start,
> int64_t len, int fl_type)
>  .l_type   = fl_type,
>  };
>  qemu_probe_lock_ops();
> -TFR(ret = fcntl(fd, fcntl_op_setlk, ));
> +ret = TEMP_FAILURE_RETRY(fcntl(fd, fcntl_op

Re: [PATCH] error handling: Use TFR() macro where applicable

2022-08-08 Thread Nikita Ivanov
t.c
@@ -102,8 +102,8 @@ static int socket_accept(int sock)
 }

 addrlen = sizeof(addr);
-TFR(
-ret = accept(sock, (struct sockaddr *), )
+ret = TEMP_FAILURE_RETRY(
+accept(sock, (struct sockaddr *), )
 );
 if (ret == -1) {
 fprintf(stderr, "%s failed: %s\n", __func__, strerror(errno));
@@ -140,7 +140,7 @@ void qtest_kill_qemu(QTestState *s)
 /* Skip wait if qtest_probe_child already reaped.  */
 if (pid != -1) {
 kill(pid, SIGTERM);
-TFR(pid = waitpid(s->qemu_pid, >wstatus, 0));
+pid = TEMP_FAILURE_RETRY(waitpid(s->qemu_pid, >wstatus, 0));
 assert(pid == s->qemu_pid);
 s->qemu_pid = -1;
 }
@@ -578,8 +578,8 @@ int qtest_socket_server(const char *socket_path)
 addr.sun_family = AF_UNIX;
 snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", socket_path);

-TFR(
-ret = bind(sock, (struct sockaddr *), sizeof(addr))
+ret = TEMP_FAILURE_RETRY(
+bind(sock, (struct sockaddr *), sizeof(addr))
 );
 g_assert_cmpint(ret, !=, -1);
 ret = listen(sock, 1);
diff --git a/tests/vhost-user-bridge.c b/tests/vhost-user-bridge.c
index 4d8f933ed5..624a211f3d 100644
--- a/tests/vhost-user-bridge.c
+++ b/tests/vhost-user-bridge.c
@@ -331,7 +331,9 @@ vubr_backend_recv_cb(int sock, void *ctx)
 .msg_iovlen = num,
 .msg_flags = MSG_DONTWAIT,
 };
-TFR(ret = recvmsg(vubr->backend_udp_sock, , 0));
+ret = TEMP_FAILURE_RETRY(
+recvmsg(vubr->backend_udp_sock, , 0)
+);

 if (i == 0) {
 iov_restore_front(elem->in_sg, sg, hdrlen);
diff --git a/util/main-loop.c b/util/main-loop.c
index 58e14db2d4..5f65f928bd 100644
--- a/util/main-loop.c
+++ b/util/main-loop.c
@@ -64,7 +64,7 @@ static void sigfd_handler(void *opaque)
 ssize_t len;

 while (1) {
-TFR(len = read(fd, , sizeof(info)));
+len = TEMP_FAILURE_RETRY(read(fd, , sizeof(info)));

 if (len == -1 && errno == EAGAIN) {
 break;
diff --git a/util/osdep.c b/util/osdep.c
index d35c473ac7..2c287e75e7 100644
--- a/util/osdep.c
+++ b/util/osdep.c
@@ -244,7 +244,7 @@ static int qemu_lock_fcntl(int fd, int64_t start,
int64_t len, int fl_type)
 .l_type   = fl_type,
 };
 qemu_probe_lock_ops();
-TFR(ret = fcntl(fd, fcntl_op_setlk, ));
+ret = TEMP_FAILURE_RETRY(fcntl(fd, fcntl_op_setlk, ));
 return ret == -1 ? -errno : 0;
 }

diff --git a/util/vfio-helpers.c b/util/vfio-helpers.c
index c878be1c5f..e1422666eb 100644
--- a/util/vfio-helpers.c
+++ b/util/vfio-helpers.c
@@ -240,8 +240,8 @@ static int qemu_vfio_pci_read_config(QEMUVFIOState *s,
void *buf,
 s->config_region_info.offset,
 s->config_region_info.size);
 assert(QEMU_IS_ALIGNED(s->config_region_info.offset + ofs, size));
-TFR(
-ret = pread(s->device, buf, size, s->config_region_info.offset +
ofs)
+ret = TEMP_FAILURE_RETRY(
+pread(s->device, buf, size, s->config_region_info.offset + ofs)
 );
 return ret == size ? 0 : -errno;
 }
@@ -254,8 +254,8 @@ static int qemu_vfio_pci_write_config(QEMUVFIOState *s,
void *buf, int size, int
  s->config_region_info.offset,
  s->config_region_info.size);
 assert(QEMU_IS_ALIGNED(s->config_region_info.offset + ofs, size));
-TFR(
-ret = pwrite(s->device, buf, size, s->config_region_info.offset +
ofs)
+ret = TEMP_FAILURE_RETRY(
+pwrite(s->device, buf, size, s->config_region_info.offset + ofs)
 );
 return ret == size ? 0 : -errno;
 }
-- 
2.37.1


On Mon, Aug 8, 2022 at 9:00 PM Nikita Ivanov  wrote:

> Hi!
> During our discussion, I found that I've missed a couple of places where
> TFR() macro could be applied. Here is an updated first patch:
>
> From 8a68f50aac4a8549f416b9350cf339cf0501a712 Mon Sep 17 00:00:00 2001
> From: Nikita Ivanov 
> Date: Wed, 3 Aug 2022 12:54:00 +0300
> Subject: [PATCH] error handling: Use TFR() macro where applicable
>
> There is a defined TFR() macro in qemu/osdep.h which
> handles the same while loop.
> Resolves: https://gitlab.com/qemu-project/qemu/-/issues/415
>
> Signed-off-by: Nikita Ivanov 
> ---
>  block/file-posix.c| 39 ++-
>  chardev/char-pty.c|  4 +---
>  hw/9pfs/9p-local.c|  8 ++--
>  net/l2tpv3.c  | 15 +++
>  net/socket.c  | 16 +++-
>  net/tap.c |  8 ++--
>  qga/commands-posix.c  |  4 +---
>  semihosting/syscalls.c|  4 +---
>  tests/qtest/libqtest.c| 14 +++---
>  tests/vhost-user-bridge.c |  4 +---
>  util/main-loop.c  |  4 +---
>  util/osd

Re: [PATCH] error handling: Use TFR() macro where applicable

2022-08-08 Thread Nikita Ivanov
Hi!
During our discussion, I found that I've missed a couple of places where
TFR() macro could be applied. Here is an updated first patch:

>From 8a68f50aac4a8549f416b9350cf339cf0501a712 Mon Sep 17 00:00:00 2001
From: Nikita Ivanov 
Date: Wed, 3 Aug 2022 12:54:00 +0300
Subject: [PATCH] error handling: Use TFR() macro where applicable

There is a defined TFR() macro in qemu/osdep.h which
handles the same while loop.
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/415

Signed-off-by: Nikita Ivanov 
---
 block/file-posix.c| 39 ++-
 chardev/char-pty.c|  4 +---
 hw/9pfs/9p-local.c|  8 ++--
 net/l2tpv3.c  | 15 +++
 net/socket.c  | 16 +++-
 net/tap.c |  8 ++--
 qga/commands-posix.c  |  4 +---
 semihosting/syscalls.c|  4 +---
 tests/qtest/libqtest.c| 14 +++---
 tests/vhost-user-bridge.c |  4 +---
 util/main-loop.c  |  4 +---
 util/osdep.c  |  4 +---
 util/vfio-helpers.c   | 12 ++--
 13 files changed, 51 insertions(+), 85 deletions(-)

diff --git a/block/file-posix.c b/block/file-posix.c
index 48cd096624..0786cb76f9 100644
--- a/block/file-posix.c
+++ b/block/file-posix.c
@@ -1238,9 +1238,9 @@ static int hdev_get_max_segments(int fd, struct stat
*st)
 ret = -errno;
 goto out;
 }
-do {
-ret = read(sysfd, buf, sizeof(buf) - 1);
-} while (ret == -1 && errno == EINTR);
+TFR(
+ret = read(sysfd, buf, sizeof(buf) - 1)
+);
 if (ret < 0) {
 ret = -errno;
 goto out;
@@ -1388,9 +1388,9 @@ static int handle_aiocb_ioctl(void *opaque)
 RawPosixAIOData *aiocb = opaque;
 int ret;

-do {
-ret = ioctl(aiocb->aio_fildes, aiocb->ioctl.cmd, aiocb->ioctl.buf);
-} while (ret == -1 && errno == EINTR);
+TFR(
+ret = ioctl(aiocb->aio_fildes, aiocb->ioctl.cmd, aiocb->ioctl.buf)
+);
 if (ret == -1) {
 return -errno;
 }
@@ -1472,18 +1472,17 @@ static ssize_t
handle_aiocb_rw_vector(RawPosixAIOData *aiocb)
 {
 ssize_t len;

-do {
-if (aiocb->aio_type & QEMU_AIO_WRITE)
-len = qemu_pwritev(aiocb->aio_fildes,
-   aiocb->io.iov,
-   aiocb->io.niov,
-   aiocb->aio_offset);
- else
-len = qemu_preadv(aiocb->aio_fildes,
-  aiocb->io.iov,
-  aiocb->io.niov,
-  aiocb->aio_offset);
-} while (len == -1 && errno == EINTR);
+TFR(
+len = (aiocb->aio_type & QEMU_AIO_WRITE) ?
+qemu_pwritev(aiocb->aio_fildes,
+   aiocb->io.iov,
+   aiocb->io.niov,
+   aiocb->aio_offset) :
+qemu_preadv(aiocb->aio_fildes,
+  aiocb->io.iov,
+  aiocb->io.niov,
+  aiocb->aio_offset)
+);

 if (len == -1) {
 return -errno;
@@ -1908,9 +1907,7 @@ static int allocate_first_block(int fd, size_t
max_size)
 buf = qemu_memalign(max_align, write_size);
 memset(buf, 0, write_size);

-do {
-n = pwrite(fd, buf, write_size, 0);
-} while (n == -1 && errno == EINTR);
+TFR(n = pwrite(fd, buf, write_size, 0));

 ret = (n == -1) ? -errno : 0;

diff --git a/chardev/char-pty.c b/chardev/char-pty.c
index 53f25c6bbd..b2f490bacf 100644
--- a/chardev/char-pty.c
+++ b/chardev/char-pty.c
@@ -93,9 +93,7 @@ static void pty_chr_update_read_handler(Chardev *chr)
 pfd.fd = fioc->fd;
 pfd.events = G_IO_OUT;
 pfd.revents = 0;
-do {
-rc = g_poll(, 1, 0);
-} while (rc == -1 && errno == EINTR);
+TFR(rc = g_poll(, 1, 0));
 assert(rc >= 0);

 if (pfd.revents & G_IO_HUP) {
diff --git a/hw/9pfs/9p-local.c b/hw/9pfs/9p-local.c
index d42ce6d8b8..c90ab947ba 100644
--- a/hw/9pfs/9p-local.c
+++ b/hw/9pfs/9p-local.c
@@ -470,9 +470,7 @@ static ssize_t local_readlink(FsContext *fs_ctx,
V9fsPath *fs_path,
 if (fd == -1) {
 return -1;
 }
-do {
-tsize = read(fd, (void *)buf, bufsz);
-} while (tsize == -1 && errno == EINTR);
+TFR(tsize = read(fd, (void *)buf, bufsz));
 close_preserve_errno(fd);
 } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
(fs_ctx->export_flags & V9FS_SM_NONE)) {
@@ -908,9 +906,7 @@ static int local_symlink(FsContext *fs_ctx, const char
*oldpath,
 }
 /* Write the oldpath (target) to the file. */
 oldpath_size = strlen(oldpath);
-do {
-write_size = write(fd, (void *)oldpath, oldpath_size);
-} while (write_s

Re: [PATCH] error handling: Use TFR() macro where applicable

2022-08-08 Thread Markus Armbruster
Christian Schoenebeck  writes:

> On Montag, 8. August 2022 14:52:28 CEST Christian Schoenebeck wrote:
>> On Montag, 8. August 2022 10:05:56 CEST Markus Armbruster wrote:
>> > Nikita Ivanov  writes:
>> > > Summing up the discussion above, I suggest the following patch for TFR()
>> > > macro refactoring. (The patch is sequential to the first one I
>> > > introduced
>> > > in the start of the discussion).
>> > > 
>> > >>From 6318bee052900aa93bba6620b53c7cb2290e5001 Mon Sep 17 00:00:00 2001
>> > >>
>> > > From: Nikita Ivanov 
>> > > Date: Mon, 8 Aug 2022 09:30:34 +0300
>> > > Subject: [PATCH] Refactoring: rename TFR() to TEMP_FAILURE_RETRY()
>> > > 
>> > > glibc's unistd.h header provides the same macro with the
>> > > subtle difference in type casting. Adjust macro name to the
>> > > common standard and define conditionally.
>> > > 
>> > > Signed-off-by: Nikita Ivanov 

[...]

>> > > diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h
>> > > index b1c161c035..55f2927d8b 100644
>> > > --- a/include/qemu/osdep.h
>> > > +++ b/include/qemu/osdep.h
>> > > @@ -242,8 +242,10 @@ void QEMU_ERROR("code path is reachable")
>> > > 
>> > >  #if !defined(ESHUTDOWN)
>> > >  #define ESHUTDOWN 4099
>> > >  #endif
>> > > 
>> > > -
>> > > -#define TFR(expr) do { if ((expr) != -1) break; } while (errno ==
>> > > EINTR)
>> > > +#if !defined(TEMP_FAILURE_RETRY)
>> > > +#define TEMP_FAILURE_RETRY(expr) \
>> > > +do { if ((expr) != -1) break; } while (errno == EINTR)

To avoid / reduce confusion: this macro expands into a statement, and ...

>> > > +#endif
>> > 
>> > GLibc's version is
>> > 
>> ># define TEMP_FAILURE_RETRY(expression) \
>> >  (__extension__
>> >   \
>> >({ long int __result;   
>> >   \
>> >   do __result = (long int) (expression);   
>> >   \
>> >   while (__result == -1L && errno == EINTR);   
>> >   \
>> >   __result; }))

... this one expands into an expression.  It uses GCC's "a compound
statement enclosed in parentheses may appear as an expression" extension.

>> > 
>> > The difference isn't just "type casting", it's also statement
>> > vs. expression.
>> > 
>> > Is it a good idea to have the macro expand into a statement on some
>> > hosts, and into an expression on others?  Sure, CI should catch any uses
>> > as expression, but delaying compile errors to CI wastes developer time.
>> 
>> For consistency and simplicity, I would define exactly one version (no
>> ifdefs) of the macro with a different macro name than glibc's
>> TEMP_FAILURE_RETRY(), and use that QEMU specific macro name in QEMU code
>> everywhere.

TFR()?  Can't resist closing the circle...

>> As for statement vs. expression: The only advantage of the statement version
>> is if you'd need __result as an rvalue, which is not needed ATM, right? So
>> I would go for the expression version (with cast) for now.

The expression-like macro is nicer where the return value matters.
Example (stolen from "The GNU C Library Reference Manual"):

nbytes = TEMP_FAILURE_RETRY (write (desc, buffer, count));

With the statement-like macro, you have to write

TEMP_FAILURE_RETRY (nbytes = write (desc, buffer, count));

>> The glibc history does not reveal why they chose the statement version.

The expression version, actually.

>> Best regards,
>> Christian Schoenebeck
>
> Sorry: s/rvalue/lvalue/ i.e. if you need the memory address of result or if 
> you need to take the result value of the last iteration in 'expression' into 
> account.




Re: [PATCH] error handling: Use TFR() macro where applicable

2022-08-08 Thread Christian Schoenebeck
On Montag, 8. August 2022 14:52:28 CEST Christian Schoenebeck wrote:
> On Montag, 8. August 2022 10:05:56 CEST Markus Armbruster wrote:
> > Nikita Ivanov  writes:
> > > Summing up the discussion above, I suggest the following patch for TFR()
> > > macro refactoring. (The patch is sequential to the first one I
> > > introduced
> > > in the start of the discussion).
> > > 
> > >>From 6318bee052900aa93bba6620b53c7cb2290e5001 Mon Sep 17 00:00:00 2001
> > >>
> > > From: Nikita Ivanov 
> > > Date: Mon, 8 Aug 2022 09:30:34 +0300
> > > Subject: [PATCH] Refactoring: rename TFR() to TEMP_FAILURE_RETRY()
> > > 
> > > glibc's unistd.h header provides the same macro with the
> > > subtle difference in type casting. Adjust macro name to the
> > > common standard and define conditionally.
> > > 
> > > Signed-off-by: Nikita Ivanov 
> > > ---
> > > 
> > >  chardev/char-fd.c  |  2 +-
> > >  chardev/char-pipe.c| 12 +---
> > >  hw/9pfs/9p-local.c |  6 --
> > >  include/qemu/osdep.h   |  6 --
> > >  net/l2tpv3.c   |  8 +---
> > >  net/tap-linux.c|  2 +-
> > >  net/tap.c  | 10 ++
> > >  os-posix.c |  2 +-
> > >  qga/commands-posix.c   |  2 +-
> > >  tests/qtest/libqtest.c |  2 +-
> > >  util/main-loop.c   |  2 +-
> > >  util/osdep.c   |  2 +-
> > >  12 files changed, 35 insertions(+), 21 deletions(-)
> > > 
> > > diff --git a/chardev/char-fd.c b/chardev/char-fd.c
> > > index cf78454841..7f5ed9aba3 100644
> > > --- a/chardev/char-fd.c
> > > +++ b/chardev/char-fd.c
> > > @@ -198,7 +198,7 @@ int qmp_chardev_open_file_source(char *src, int
> > > flags,
> > > Error **errp)
> > > 
> > >  {
> > >  
> > >  int fd = -1;
> > > 
> > > -TFR(fd = qemu_open_old(src, flags, 0666));
> > > +TEMP_FAILURE_RETRY(fd = qemu_open_old(src, flags, 0666));
> > > 
> > >  if (fd == -1) {
> > >  
> > >  error_setg_file_open(errp, errno, src);
> > >  
> > >  }
> > > 
> > > diff --git a/chardev/char-pipe.c b/chardev/char-pipe.c
> > > index 66d3b85091..aed97e306b 100644
> > > --- a/chardev/char-pipe.c
> > > +++ b/chardev/char-pipe.c
> > > @@ -131,8 +131,12 @@ static void qemu_chr_open_pipe(Chardev *chr,
> > > 
> > >  filename_in = g_strdup_printf("%s.in", filename);
> > >  filename_out = g_strdup_printf("%s.out", filename);
> > > 
> > > -TFR(fd_in = qemu_open_old(filename_in, O_RDWR | O_BINARY));
> > > -TFR(fd_out = qemu_open_old(filename_out, O_RDWR | O_BINARY));
> > > +TEMP_FAILURE_RETRY(
> > > +fd_in = qemu_open_old(filename_in, O_RDWR | O_BINARY)
> > > +);
> > > +TEMP_FAILURE_RETRY(
> > > +fd_out = qemu_open_old(filename_out, O_RDWR | O_BINARY)
> > > +);
> > 
> > Style question: do we want the ");" on its own line?  I think we
> > generally don't do that for function and function-like macro calls.
> 
> So far scripts/checkpatch.pl doesn't complain, therefore I used this code
> style in QEMU before.
> 
> BTW, another exotic function call code style (not being compalained about
> yet) in approach:
> https://lore.kernel.org/qemu-devel/e1odqqv-0003d4...@lizzy.crudebyte.com/
> 
> > >  g_free(filename_in);
> > >  g_free(filename_out);
> > >  if (fd_in < 0 || fd_out < 0) {
> > > 
> > > @@ -142,7 +146,9 @@ static void qemu_chr_open_pipe(Chardev *chr,
> > > 
> > >  if (fd_out >= 0) {
> > >  
> > >  close(fd_out);
> > >  
> > >  }
> > > 
> > > -TFR(fd_in = fd_out = qemu_open_old(filename, O_RDWR |
> > > O_BINARY));
> > > +TEMP_FAILURE_RETRY(
> > > +fd_in = fd_out = qemu_open_old(filename, O_RDWR | O_BINARY)
> > > +);
> > > 
> > >  if (fd_in < 0) {
> > >  
> > >  error_setg_file_open(errp, errno, filename);
> > >  return;
> > > 
> > > diff --git a/hw/9pfs/9p-local.c b/hw/9pfs/9p-local.c
> > > index c90ab947ba..e803c05d0c 100644
> > > --- a/hw/9pfs/9p-local.c
> > > +++ b/hw/9pfs/9p-local.c
> > > @@ -470,7 +470,7 @@ static ssize_t local_readlink(FsContext *fs_ctx,
> > > V9fsPath *fs_path,
> > > 
> > >  if (fd == -1) {
> > >  
> > >  return -1;
> > >  
> > >  }
> > > 
> > > -TFR(tsize = read(fd, (void *)buf, bufsz));
> > > +TEMP_FAILURE_RETRY(tsize = read(fd, (void *)buf, bufsz));
> > > 
> > >  close_preserve_errno(fd);
> > >  
> > >  } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
> > >  
> > > (fs_ctx->export_flags & V9FS_SM_NONE)) {
> > > 
> > > @@ -906,7 +906,9 @@ static int local_symlink(FsContext *fs_ctx, const
> > > char
> > > *oldpath,
> > > 
> > >  }
> > >  /* Write the oldpath (target) to the file. */
> > >  oldpath_size = strlen(oldpath);
> > > 
> > > -TFR(write_size = write(fd, (void *)oldpath, oldpath_size));
> > > +TEMP_FAILURE_RETRY(
> > > +write_size = write(fd, (void *)oldpath, oldpath_size)
> 

Re: [PATCH] error handling: Use TFR() macro where applicable

2022-08-08 Thread Christian Schoenebeck
On Montag, 8. August 2022 10:05:56 CEST Markus Armbruster wrote:
> Nikita Ivanov  writes:
> > Summing up the discussion above, I suggest the following patch for TFR()
> > macro refactoring. (The patch is sequential to the first one I introduced
> > in the start of the discussion).
> > 
> >>From 6318bee052900aa93bba6620b53c7cb2290e5001 Mon Sep 17 00:00:00 2001
> >>
> > From: Nikita Ivanov 
> > Date: Mon, 8 Aug 2022 09:30:34 +0300
> > Subject: [PATCH] Refactoring: rename TFR() to TEMP_FAILURE_RETRY()
> > 
> > glibc's unistd.h header provides the same macro with the
> > subtle difference in type casting. Adjust macro name to the
> > common standard and define conditionally.
> > 
> > Signed-off-by: Nikita Ivanov 
> > ---
> > 
> >  chardev/char-fd.c  |  2 +-
> >  chardev/char-pipe.c| 12 +---
> >  hw/9pfs/9p-local.c |  6 --
> >  include/qemu/osdep.h   |  6 --
> >  net/l2tpv3.c   |  8 +---
> >  net/tap-linux.c|  2 +-
> >  net/tap.c  | 10 ++
> >  os-posix.c |  2 +-
> >  qga/commands-posix.c   |  2 +-
> >  tests/qtest/libqtest.c |  2 +-
> >  util/main-loop.c   |  2 +-
> >  util/osdep.c   |  2 +-
> >  12 files changed, 35 insertions(+), 21 deletions(-)
> > 
> > diff --git a/chardev/char-fd.c b/chardev/char-fd.c
> > index cf78454841..7f5ed9aba3 100644
> > --- a/chardev/char-fd.c
> > +++ b/chardev/char-fd.c
> > @@ -198,7 +198,7 @@ int qmp_chardev_open_file_source(char *src, int flags,
> > Error **errp)
> > 
> >  {
> >  
> >  int fd = -1;
> > 
> > -TFR(fd = qemu_open_old(src, flags, 0666));
> > +TEMP_FAILURE_RETRY(fd = qemu_open_old(src, flags, 0666));
> > 
> >  if (fd == -1) {
> >  
> >  error_setg_file_open(errp, errno, src);
> >  
> >  }
> > 
> > diff --git a/chardev/char-pipe.c b/chardev/char-pipe.c
> > index 66d3b85091..aed97e306b 100644
> > --- a/chardev/char-pipe.c
> > +++ b/chardev/char-pipe.c
> > @@ -131,8 +131,12 @@ static void qemu_chr_open_pipe(Chardev *chr,
> > 
> >  filename_in = g_strdup_printf("%s.in", filename);
> >  filename_out = g_strdup_printf("%s.out", filename);
> > 
> > -TFR(fd_in = qemu_open_old(filename_in, O_RDWR | O_BINARY));
> > -TFR(fd_out = qemu_open_old(filename_out, O_RDWR | O_BINARY));
> > +TEMP_FAILURE_RETRY(
> > +fd_in = qemu_open_old(filename_in, O_RDWR | O_BINARY)
> > +);
> > +TEMP_FAILURE_RETRY(
> > +fd_out = qemu_open_old(filename_out, O_RDWR | O_BINARY)
> > +);
> 
> Style question: do we want the ");" on its own line?  I think we
> generally don't do that for function and function-like macro calls.

So far scripts/checkpatch.pl doesn't complain, therefore I used this code 
style in QEMU before.

BTW, another exotic function call code style (not being compalained about yet) 
in approach:
https://lore.kernel.org/qemu-devel/e1odqqv-0003d4...@lizzy.crudebyte.com/

> >  g_free(filename_in);
> >  g_free(filename_out);
> >  if (fd_in < 0 || fd_out < 0) {
> > 
> > @@ -142,7 +146,9 @@ static void qemu_chr_open_pipe(Chardev *chr,
> > 
> >  if (fd_out >= 0) {
> >  
> >  close(fd_out);
> >  
> >  }
> > 
> > -TFR(fd_in = fd_out = qemu_open_old(filename, O_RDWR | O_BINARY));
> > +TEMP_FAILURE_RETRY(
> > +fd_in = fd_out = qemu_open_old(filename, O_RDWR | O_BINARY)
> > +);
> > 
> >  if (fd_in < 0) {
> >  
> >  error_setg_file_open(errp, errno, filename);
> >  return;
> > 
> > diff --git a/hw/9pfs/9p-local.c b/hw/9pfs/9p-local.c
> > index c90ab947ba..e803c05d0c 100644
> > --- a/hw/9pfs/9p-local.c
> > +++ b/hw/9pfs/9p-local.c
> > @@ -470,7 +470,7 @@ static ssize_t local_readlink(FsContext *fs_ctx,
> > V9fsPath *fs_path,
> > 
> >  if (fd == -1) {
> >  
> >  return -1;
> >  
> >  }
> > 
> > -TFR(tsize = read(fd, (void *)buf, bufsz));
> > +TEMP_FAILURE_RETRY(tsize = read(fd, (void *)buf, bufsz));
> > 
> >  close_preserve_errno(fd);
> >  
> >  } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
> >  
> > (fs_ctx->export_flags & V9FS_SM_NONE)) {
> > 
> > @@ -906,7 +906,9 @@ static int local_symlink(FsContext *fs_ctx, const char
> > *oldpath,
> > 
> >  }
> >  /* Write the oldpath (target) to the file. */
> >  oldpath_size = strlen(oldpath);
> > 
> > -TFR(write_size = write(fd, (void *)oldpath, oldpath_size));
> > +TEMP_FAILURE_RETRY(
> > +write_size = write(fd, (void *)oldpath, oldpath_size)
> > +);
> > 
> >  close_preserve_errno(fd);
> >  
> >  if (write_size != oldpath_size) {
> > 
> > diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h
> > index b1c161c035..55f2927d8b 100644
> > --- a/include/qemu/osdep.h
> > +++ b/include/qemu/osdep.h
> > @@ -242,8 +242,10 @@ void QEMU_ERROR("code path is reachable")
> > 
> 

Re: [PATCH] error handling: Use TFR() macro where applicable

2022-08-08 Thread Nikita Ivanov
Good point, thank you!
I think it's a bad idea to keep it like I proposed. Though, could I just
copy the definition that Markus has posted or there are any objections?

On Mon, Aug 8, 2022 at 11:06 AM Markus Armbruster  wrote:

> Nikita Ivanov  writes:
>
> > Summing up the discussion above, I suggest the following patch for TFR()
> > macro refactoring. (The patch is sequential to the first one I introduced
> > in the start of the discussion).
> >
> >>From 6318bee052900aa93bba6620b53c7cb2290e5001 Mon Sep 17 00:00:00 2001
> > From: Nikita Ivanov 
> > Date: Mon, 8 Aug 2022 09:30:34 +0300
> > Subject: [PATCH] Refactoring: rename TFR() to TEMP_FAILURE_RETRY()
> >
> > glibc's unistd.h header provides the same macro with the
> > subtle difference in type casting. Adjust macro name to the
> > common standard and define conditionally.
> >
> > Signed-off-by: Nikita Ivanov 
> > ---
> >  chardev/char-fd.c  |  2 +-
> >  chardev/char-pipe.c| 12 +---
> >  hw/9pfs/9p-local.c |  6 --
> >  include/qemu/osdep.h   |  6 --
> >  net/l2tpv3.c   |  8 +---
> >  net/tap-linux.c|  2 +-
> >  net/tap.c  | 10 ++
> >  os-posix.c |  2 +-
> >  qga/commands-posix.c   |  2 +-
> >  tests/qtest/libqtest.c |  2 +-
> >  util/main-loop.c   |  2 +-
> >  util/osdep.c   |  2 +-
> >  12 files changed, 35 insertions(+), 21 deletions(-)
> >
> > diff --git a/chardev/char-fd.c b/chardev/char-fd.c
> > index cf78454841..7f5ed9aba3 100644
> > --- a/chardev/char-fd.c
> > +++ b/chardev/char-fd.c
> > @@ -198,7 +198,7 @@ int qmp_chardev_open_file_source(char *src, int
> flags,
> > Error **errp)
> >  {
> >  int fd = -1;
> >
> > -TFR(fd = qemu_open_old(src, flags, 0666));
> > +TEMP_FAILURE_RETRY(fd = qemu_open_old(src, flags, 0666));
> >  if (fd == -1) {
> >  error_setg_file_open(errp, errno, src);
> >  }
> > diff --git a/chardev/char-pipe.c b/chardev/char-pipe.c
> > index 66d3b85091..aed97e306b 100644
> > --- a/chardev/char-pipe.c
> > +++ b/chardev/char-pipe.c
> > @@ -131,8 +131,12 @@ static void qemu_chr_open_pipe(Chardev *chr,
> >
> >  filename_in = g_strdup_printf("%s.in", filename);
> >  filename_out = g_strdup_printf("%s.out", filename);
> > -TFR(fd_in = qemu_open_old(filename_in, O_RDWR | O_BINARY));
> > -TFR(fd_out = qemu_open_old(filename_out, O_RDWR | O_BINARY));
> > +TEMP_FAILURE_RETRY(
> > +fd_in = qemu_open_old(filename_in, O_RDWR | O_BINARY)
> > +);
> > +TEMP_FAILURE_RETRY(
> > +fd_out = qemu_open_old(filename_out, O_RDWR | O_BINARY)
> > +);
>
> Style question: do we want the ");" on its own line?  I think we
> generally don't do that for function and function-like macro calls.
>
> >  g_free(filename_in);
> >  g_free(filename_out);
> >  if (fd_in < 0 || fd_out < 0) {
> > @@ -142,7 +146,9 @@ static void qemu_chr_open_pipe(Chardev *chr,
> >  if (fd_out >= 0) {
> >  close(fd_out);
> >  }
> > -TFR(fd_in = fd_out = qemu_open_old(filename, O_RDWR |
> O_BINARY));
> > +TEMP_FAILURE_RETRY(
> > +fd_in = fd_out = qemu_open_old(filename, O_RDWR | O_BINARY)
> > +);
> >  if (fd_in < 0) {
> >  error_setg_file_open(errp, errno, filename);
> >  return;
> > diff --git a/hw/9pfs/9p-local.c b/hw/9pfs/9p-local.c
> > index c90ab947ba..e803c05d0c 100644
> > --- a/hw/9pfs/9p-local.c
> > +++ b/hw/9pfs/9p-local.c
> > @@ -470,7 +470,7 @@ static ssize_t local_readlink(FsContext *fs_ctx,
> > V9fsPath *fs_path,
> >  if (fd == -1) {
> >  return -1;
> >  }
> > -TFR(tsize = read(fd, (void *)buf, bufsz));
> > +TEMP_FAILURE_RETRY(tsize = read(fd, (void *)buf, bufsz));
> >  close_preserve_errno(fd);
> >  } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
> > (fs_ctx->export_flags & V9FS_SM_NONE)) {
> > @@ -906,7 +906,9 @@ static int local_symlink(FsContext *fs_ctx, const
> char
> > *oldpath,
> >  }
> >  /* Write the oldpath (target) to the file. */
> >  oldpath_size = strlen(oldpath);
> > -TFR(write_size = write(fd, (void *)oldpath, oldpath_size));
> > +TEMP_FAILURE_RETRY(
> > +write_size = write(fd, (void *)oldpath, oldpath_size)
> > +);
> >  close_preserve_errno(fd);
> >
> >  if (write_size != oldpath_size) {
> > diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h
> > index b1c161c035..55f2927d8b 100644
> > --- a/include/qemu/osdep.h
> > +++ b/include/qemu/osdep.h
> > @@ -242,8 +242,10 @@ void QEMU_ERROR("code path is reachable")
> >  #if !defined(ESHUTDOWN)
> >  #define ESHUTDOWN 4099
> >  #endif
> > -
> > -#define TFR(expr) do { if ((expr) != -1) break; } while (errno == EINTR)
> > +#if !defined(TEMP_FAILURE_RETRY)
> > +#define TEMP_FAILURE_RETRY(expr) \
> > +do { if ((expr) != -1) break; } while (errno == EINTR)
> > +#endif
>
> GLibc's version 

Re: [PATCH] error handling: Use TFR() macro where applicable

2022-08-08 Thread Markus Armbruster
Nikita Ivanov  writes:

> Summing up the discussion above, I suggest the following patch for TFR()
> macro refactoring. (The patch is sequential to the first one I introduced
> in the start of the discussion).
>
>>From 6318bee052900aa93bba6620b53c7cb2290e5001 Mon Sep 17 00:00:00 2001
> From: Nikita Ivanov 
> Date: Mon, 8 Aug 2022 09:30:34 +0300
> Subject: [PATCH] Refactoring: rename TFR() to TEMP_FAILURE_RETRY()
>
> glibc's unistd.h header provides the same macro with the
> subtle difference in type casting. Adjust macro name to the
> common standard and define conditionally.
>
> Signed-off-by: Nikita Ivanov 
> ---
>  chardev/char-fd.c  |  2 +-
>  chardev/char-pipe.c| 12 +---
>  hw/9pfs/9p-local.c |  6 --
>  include/qemu/osdep.h   |  6 --
>  net/l2tpv3.c   |  8 +---
>  net/tap-linux.c|  2 +-
>  net/tap.c  | 10 ++
>  os-posix.c |  2 +-
>  qga/commands-posix.c   |  2 +-
>  tests/qtest/libqtest.c |  2 +-
>  util/main-loop.c   |  2 +-
>  util/osdep.c   |  2 +-
>  12 files changed, 35 insertions(+), 21 deletions(-)
>
> diff --git a/chardev/char-fd.c b/chardev/char-fd.c
> index cf78454841..7f5ed9aba3 100644
> --- a/chardev/char-fd.c
> +++ b/chardev/char-fd.c
> @@ -198,7 +198,7 @@ int qmp_chardev_open_file_source(char *src, int flags,
> Error **errp)
>  {
>  int fd = -1;
>
> -TFR(fd = qemu_open_old(src, flags, 0666));
> +TEMP_FAILURE_RETRY(fd = qemu_open_old(src, flags, 0666));
>  if (fd == -1) {
>  error_setg_file_open(errp, errno, src);
>  }
> diff --git a/chardev/char-pipe.c b/chardev/char-pipe.c
> index 66d3b85091..aed97e306b 100644
> --- a/chardev/char-pipe.c
> +++ b/chardev/char-pipe.c
> @@ -131,8 +131,12 @@ static void qemu_chr_open_pipe(Chardev *chr,
>
>  filename_in = g_strdup_printf("%s.in", filename);
>  filename_out = g_strdup_printf("%s.out", filename);
> -TFR(fd_in = qemu_open_old(filename_in, O_RDWR | O_BINARY));
> -TFR(fd_out = qemu_open_old(filename_out, O_RDWR | O_BINARY));
> +TEMP_FAILURE_RETRY(
> +fd_in = qemu_open_old(filename_in, O_RDWR | O_BINARY)
> +);
> +TEMP_FAILURE_RETRY(
> +fd_out = qemu_open_old(filename_out, O_RDWR | O_BINARY)
> +);

Style question: do we want the ");" on its own line?  I think we
generally don't do that for function and function-like macro calls.

>  g_free(filename_in);
>  g_free(filename_out);
>  if (fd_in < 0 || fd_out < 0) {
> @@ -142,7 +146,9 @@ static void qemu_chr_open_pipe(Chardev *chr,
>  if (fd_out >= 0) {
>  close(fd_out);
>  }
> -TFR(fd_in = fd_out = qemu_open_old(filename, O_RDWR | O_BINARY));
> +TEMP_FAILURE_RETRY(
> +fd_in = fd_out = qemu_open_old(filename, O_RDWR | O_BINARY)
> +);
>  if (fd_in < 0) {
>  error_setg_file_open(errp, errno, filename);
>  return;
> diff --git a/hw/9pfs/9p-local.c b/hw/9pfs/9p-local.c
> index c90ab947ba..e803c05d0c 100644
> --- a/hw/9pfs/9p-local.c
> +++ b/hw/9pfs/9p-local.c
> @@ -470,7 +470,7 @@ static ssize_t local_readlink(FsContext *fs_ctx,
> V9fsPath *fs_path,
>  if (fd == -1) {
>  return -1;
>  }
> -TFR(tsize = read(fd, (void *)buf, bufsz));
> +TEMP_FAILURE_RETRY(tsize = read(fd, (void *)buf, bufsz));
>  close_preserve_errno(fd);
>  } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
> (fs_ctx->export_flags & V9FS_SM_NONE)) {
> @@ -906,7 +906,9 @@ static int local_symlink(FsContext *fs_ctx, const char
> *oldpath,
>  }
>  /* Write the oldpath (target) to the file. */
>  oldpath_size = strlen(oldpath);
> -TFR(write_size = write(fd, (void *)oldpath, oldpath_size));
> +TEMP_FAILURE_RETRY(
> +write_size = write(fd, (void *)oldpath, oldpath_size)
> +);
>  close_preserve_errno(fd);
>
>  if (write_size != oldpath_size) {
> diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h
> index b1c161c035..55f2927d8b 100644
> --- a/include/qemu/osdep.h
> +++ b/include/qemu/osdep.h
> @@ -242,8 +242,10 @@ void QEMU_ERROR("code path is reachable")
>  #if !defined(ESHUTDOWN)
>  #define ESHUTDOWN 4099
>  #endif
> -
> -#define TFR(expr) do { if ((expr) != -1) break; } while (errno == EINTR)
> +#if !defined(TEMP_FAILURE_RETRY)
> +#define TEMP_FAILURE_RETRY(expr) \
> +do { if ((expr) != -1) break; } while (errno == EINTR)
> +#endif

GLibc's version is

   # define TEMP_FAILURE_RETRY(expression) \
 (__extension__   \
   ({ long int __result;  \
  do __result = (long int) (expression);
  \
  while (__result == -1L && errno == EINTR);  \
  __result; }))

The difference isn't just "type casting", it's also statement
vs. 

Re: [PATCH] error handling: Use TFR() macro where applicable

2022-08-08 Thread Nikita Ivanov
Summing up the discussion above, I suggest the following patch for TFR()
macro refactoring. (The patch is sequential to the first one I introduced
in the start of the discussion).

>From 6318bee052900aa93bba6620b53c7cb2290e5001 Mon Sep 17 00:00:00 2001
From: Nikita Ivanov 
Date: Mon, 8 Aug 2022 09:30:34 +0300
Subject: [PATCH] Refactoring: rename TFR() to TEMP_FAILURE_RETRY()

glibc's unistd.h header provides the same macro with the
subtle difference in type casting. Adjust macro name to the
common standard and define conditionally.

Signed-off-by: Nikita Ivanov 
---
 chardev/char-fd.c  |  2 +-
 chardev/char-pipe.c| 12 +---
 hw/9pfs/9p-local.c |  6 --
 include/qemu/osdep.h   |  6 --
 net/l2tpv3.c   |  8 +---
 net/tap-linux.c|  2 +-
 net/tap.c  | 10 ++
 os-posix.c |  2 +-
 qga/commands-posix.c   |  2 +-
 tests/qtest/libqtest.c |  2 +-
 util/main-loop.c   |  2 +-
 util/osdep.c   |  2 +-
 12 files changed, 35 insertions(+), 21 deletions(-)

diff --git a/chardev/char-fd.c b/chardev/char-fd.c
index cf78454841..7f5ed9aba3 100644
--- a/chardev/char-fd.c
+++ b/chardev/char-fd.c
@@ -198,7 +198,7 @@ int qmp_chardev_open_file_source(char *src, int flags,
Error **errp)
 {
 int fd = -1;

-TFR(fd = qemu_open_old(src, flags, 0666));
+TEMP_FAILURE_RETRY(fd = qemu_open_old(src, flags, 0666));
 if (fd == -1) {
 error_setg_file_open(errp, errno, src);
 }
diff --git a/chardev/char-pipe.c b/chardev/char-pipe.c
index 66d3b85091..aed97e306b 100644
--- a/chardev/char-pipe.c
+++ b/chardev/char-pipe.c
@@ -131,8 +131,12 @@ static void qemu_chr_open_pipe(Chardev *chr,

 filename_in = g_strdup_printf("%s.in", filename);
 filename_out = g_strdup_printf("%s.out", filename);
-TFR(fd_in = qemu_open_old(filename_in, O_RDWR | O_BINARY));
-TFR(fd_out = qemu_open_old(filename_out, O_RDWR | O_BINARY));
+TEMP_FAILURE_RETRY(
+fd_in = qemu_open_old(filename_in, O_RDWR | O_BINARY)
+);
+TEMP_FAILURE_RETRY(
+fd_out = qemu_open_old(filename_out, O_RDWR | O_BINARY)
+);
 g_free(filename_in);
 g_free(filename_out);
 if (fd_in < 0 || fd_out < 0) {
@@ -142,7 +146,9 @@ static void qemu_chr_open_pipe(Chardev *chr,
 if (fd_out >= 0) {
 close(fd_out);
 }
-TFR(fd_in = fd_out = qemu_open_old(filename, O_RDWR | O_BINARY));
+TEMP_FAILURE_RETRY(
+fd_in = fd_out = qemu_open_old(filename, O_RDWR | O_BINARY)
+);
 if (fd_in < 0) {
 error_setg_file_open(errp, errno, filename);
 return;
diff --git a/hw/9pfs/9p-local.c b/hw/9pfs/9p-local.c
index c90ab947ba..e803c05d0c 100644
--- a/hw/9pfs/9p-local.c
+++ b/hw/9pfs/9p-local.c
@@ -470,7 +470,7 @@ static ssize_t local_readlink(FsContext *fs_ctx,
V9fsPath *fs_path,
 if (fd == -1) {
 return -1;
 }
-TFR(tsize = read(fd, (void *)buf, bufsz));
+TEMP_FAILURE_RETRY(tsize = read(fd, (void *)buf, bufsz));
 close_preserve_errno(fd);
 } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
(fs_ctx->export_flags & V9FS_SM_NONE)) {
@@ -906,7 +906,9 @@ static int local_symlink(FsContext *fs_ctx, const char
*oldpath,
 }
 /* Write the oldpath (target) to the file. */
 oldpath_size = strlen(oldpath);
-TFR(write_size = write(fd, (void *)oldpath, oldpath_size));
+TEMP_FAILURE_RETRY(
+write_size = write(fd, (void *)oldpath, oldpath_size)
+);
 close_preserve_errno(fd);

 if (write_size != oldpath_size) {
diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h
index b1c161c035..55f2927d8b 100644
--- a/include/qemu/osdep.h
+++ b/include/qemu/osdep.h
@@ -242,8 +242,10 @@ void QEMU_ERROR("code path is reachable")
 #if !defined(ESHUTDOWN)
 #define ESHUTDOWN 4099
 #endif
-
-#define TFR(expr) do { if ((expr) != -1) break; } while (errno == EINTR)
+#if !defined(TEMP_FAILURE_RETRY)
+#define TEMP_FAILURE_RETRY(expr) \
+do { if ((expr) != -1) break; } while (errno == EINTR)
+#endif

 /* time_t may be either 32 or 64 bits depending on the host OS, and
  * can be either signed or unsigned, so we can't just hardcode a
diff --git a/net/l2tpv3.c b/net/l2tpv3.c
index adfdbdb84c..9594047ddb 100644
--- a/net/l2tpv3.c
+++ b/net/l2tpv3.c
@@ -240,7 +240,7 @@ static ssize_t
net_l2tpv3_receive_dgram_iov(NetClientState *nc,
 message.msg_control = NULL;
 message.msg_controllen = 0;
 message.msg_flags = 0;
-TFR(ret = sendmsg(s->fd, , 0));
+TEMP_FAILURE_RETRY(ret = sendmsg(s->fd, , 0));
 if (ret > 0) {
 ret -= s->offset;
 } else if (ret == 0) {
@@ -283,7 +283,7 @@ static ssize_t net_l2tpv3_receive_dgram(NetClientState
*nc,
 message.msg_control = NULL;
 message.msg_controllen = 0;
 message.msg_flags = 0;
-TFR(ret = sendmsg(s->fd, , 0));
+TEMP_FAILURE_RETRY(ret = sendmsg(s->fd, , 0));
 if 

Re: [PATCH] error handling: Use TFR() macro where applicable

2022-08-05 Thread Peter Maydell
On Fri, 5 Aug 2022 at 12:27, Marc-André Lureau
 wrote:
> On Fri, Aug 5, 2022 at 3:11 PM Christian Schoenebeck
>  wrote:
> > I was thinking the same as Marc-André before:
> >
> > commit 1dacd88ddcf33eb6ed044c4080e3ef5e3de4b6b6
> > Author: Marc-André Lureau 
> > Date:   Wed Mar 23 19:57:27 2022 +0400
> >
> > include: move TFR to osdep.h
> >
> > The macro requires EINTR, which has its header included in osdep.h.
> >
> > (Not sure what TFR stands for, perhaps "Test For Retry". Rename it ?)
> >
> > Signed-off-by: Marc-André Lureau 
> > Message-Id: <20220323155743.1585078-17-marcandre.lur...@redhat.com>
> > Signed-off-by: Paolo Bonzini 
> >
> > Wouldn't it make sense to first rename TFR() to something like
> > RETRY_ON_EINTR() and then doing this consolidation here on top?
>
> Apparently TFR often stands for "Temp Failure Retry" (looking at
> github code search)
>
> LOOP_WHILE_EINTR ?

At the risk of getting into bikeshedding, since glibc's unistd.h
defines a TEMP_FAILURE_RETRY() macro for this purpose, maybe we
should use that, with a thing in osdep.h for "provide this macro
if the system headers don't [ie musl, BSDs, Windows, etc]" ?

(There is a subtle difference between our TFR() and the glibc
TEMP_FAILURE_RETRY(): TEMP_FAILURE_RETRY() casts the result
of the expr to 'long int' before comparing for equality with -1.)

More generally, I think we should either use this macro rather
more widely, or get rid of it entirely. The current situation
where we use it in some of the net/tap code and a few chardevs
and basically nowhere else is not very satisfactory.

thanks
-- PMM



Re: [PATCH] error handling: Use TFR() macro where applicable

2022-08-05 Thread Marc-André Lureau
Hi

On Fri, Aug 5, 2022 at 3:11 PM Christian Schoenebeck
 wrote:
>
> On Donnerstag, 4. August 2022 09:25:17 CEST Nikita Ivanov wrote:
> > From 0ceb04ada1ed5a863914f4449469d7572d3443ed Mon Sep 17 00:00:00 2001
> > From: Nikita Ivanov 
> > Date: Wed, 3 Aug 2022 12:54:00 +0300
> > Subject: [PATCH] error handling: Use TFR() macro where applicable
> >
> > There is a defined TFR() macro in qemu/osdep.h which
> > handles the same while loop.
> > Resolves: https://gitlab.com/qemu-project/qemu/-/issues/415
> >
> > Signed-off-by: Nikita Ivanov 
> > ---
> >  hw/9pfs/9p-local.c   |  8 ++--
> >  net/l2tpv3.c | 15 +++
> >  net/tap.c|  8 ++--
> >  qga/commands-posix.c |  4 +---
> >  util/main-loop.c |  4 +---
> >  util/osdep.c |  4 +---
> >  6 files changed, 10 insertions(+), 33 deletions(-)
>
> I was thinking the same as Marc-André before:
>
> commit 1dacd88ddcf33eb6ed044c4080e3ef5e3de4b6b6
> Author: Marc-André Lureau 
> Date:   Wed Mar 23 19:57:27 2022 +0400
>
> include: move TFR to osdep.h
>
> The macro requires EINTR, which has its header included in osdep.h.
>
> (Not sure what TFR stands for, perhaps "Test For Retry". Rename it ?)
>
> Signed-off-by: Marc-André Lureau 
> Message-Id: <20220323155743.1585078-17-marcandre.lur...@redhat.com>
> Signed-off-by: Paolo Bonzini 
>
> Wouldn't it make sense to first rename TFR() to something like
> RETRY_ON_EINTR() and then doing this consolidation here on top?

Apparently TFR often stands for "Temp Failure Retry" (looking at
github code search)

LOOP_WHILE_EINTR ?

>
> Best regards,
> Christian Schoenebeck
>
> > diff --git a/hw/9pfs/9p-local.c b/hw/9pfs/9p-local.c
> > index d42ce6d8b8..c90ab947ba 100644
> > --- a/hw/9pfs/9p-local.c
> > +++ b/hw/9pfs/9p-local.c
> > @@ -470,9 +470,7 @@ static ssize_t local_readlink(FsContext *fs_ctx,
> > V9fsPath *fs_path,
> >  if (fd == -1) {
> >  return -1;
> >  }
> > -do {
> > -tsize = read(fd, (void *)buf, bufsz);
> > -} while (tsize == -1 && errno == EINTR);
> > +TFR(tsize = read(fd, (void *)buf, bufsz));
> >  close_preserve_errno(fd);
> >  } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
> > (fs_ctx->export_flags & V9FS_SM_NONE)) {
> > @@ -908,9 +906,7 @@ static int local_symlink(FsContext *fs_ctx, const char
> > *oldpath,
> >  }
> >  /* Write the oldpath (target) to the file. */
> >  oldpath_size = strlen(oldpath);
> > -do {
> > -write_size = write(fd, (void *)oldpath, oldpath_size);
> > -} while (write_size == -1 && errno == EINTR);
> > +TFR(write_size = write(fd, (void *)oldpath, oldpath_size));
> >  close_preserve_errno(fd);
> >
> >  if (write_size != oldpath_size) {
> > diff --git a/net/l2tpv3.c b/net/l2tpv3.c
> > index af373e5c30..adfdbdb84c 100644
> > --- a/net/l2tpv3.c
> > +++ b/net/l2tpv3.c
> > @@ -240,9 +240,7 @@ static ssize_t
> > net_l2tpv3_receive_dgram_iov(NetClientState *nc,
> >  message.msg_control = NULL;
> >  message.msg_controllen = 0;
> >  message.msg_flags = 0;
> > -do {
> > -ret = sendmsg(s->fd, , 0);
> > -} while ((ret == -1) && (errno == EINTR));
> > +TFR(ret = sendmsg(s->fd, , 0));
> >  if (ret > 0) {
> >  ret -= s->offset;
> >  } else if (ret == 0) {
> > @@ -285,9 +283,7 @@ static ssize_t net_l2tpv3_receive_dgram(NetClientState
> > *nc,
> >  message.msg_control = NULL;
> >  message.msg_controllen = 0;
> >  message.msg_flags = 0;
> > -do {
> > -ret = sendmsg(s->fd, , 0);
> > -} while ((ret == -1) && (errno == EINTR));
> > +TFR(ret = sendmsg(s->fd, , 0));
> >  if (ret > 0) {
> >  ret -= s->offset;
> >  } else if (ret == 0) {
> > @@ -434,12 +430,7 @@ static void net_l2tpv3_send(void *opaque)
> >
> >  msgvec = s->msgvec + s->queue_head;
> >  if (target_count > 0) {
> > -do {
> > -count = recvmmsg(
> > -s->fd,
> > -msgvec,
> > -target_count, MSG_DONTWAIT, NULL);
> > -} while ((count == -1) && (errno == EINTR));
> > +TFR(count = recvmmsg(s->fd, msgvec, target_count, MSG_DONTWAIT,
> &

Re: [PATCH] error handling: Use TFR() macro where applicable

2022-08-05 Thread Christian Schoenebeck
On Donnerstag, 4. August 2022 09:25:17 CEST Nikita Ivanov wrote:
> From 0ceb04ada1ed5a863914f4449469d7572d3443ed Mon Sep 17 00:00:00 2001
> From: Nikita Ivanov 
> Date: Wed, 3 Aug 2022 12:54:00 +0300
> Subject: [PATCH] error handling: Use TFR() macro where applicable
> 
> There is a defined TFR() macro in qemu/osdep.h which
> handles the same while loop.
> Resolves: https://gitlab.com/qemu-project/qemu/-/issues/415
> 
> Signed-off-by: Nikita Ivanov 
> ---
>  hw/9pfs/9p-local.c   |  8 ++--
>  net/l2tpv3.c | 15 +++
>  net/tap.c|  8 ++--
>  qga/commands-posix.c |  4 +---
>  util/main-loop.c |  4 +---
>  util/osdep.c |  4 +---
>  6 files changed, 10 insertions(+), 33 deletions(-)

I was thinking the same as Marc-André before:

commit 1dacd88ddcf33eb6ed044c4080e3ef5e3de4b6b6
Author: Marc-André Lureau 
Date:   Wed Mar 23 19:57:27 2022 +0400

include: move TFR to osdep.h

The macro requires EINTR, which has its header included in osdep.h.

(Not sure what TFR stands for, perhaps "Test For Retry". Rename it ?)

Signed-off-by: Marc-André Lureau 
Message-Id: <20220323155743.1585078-17-marcandre.lur...@redhat.com>
Signed-off-by: Paolo Bonzini 

Wouldn't it make sense to first rename TFR() to something like 
RETRY_ON_EINTR() and then doing this consolidation here on top?

Best regards,
Christian Schoenebeck

> diff --git a/hw/9pfs/9p-local.c b/hw/9pfs/9p-local.c
> index d42ce6d8b8..c90ab947ba 100644
> --- a/hw/9pfs/9p-local.c
> +++ b/hw/9pfs/9p-local.c
> @@ -470,9 +470,7 @@ static ssize_t local_readlink(FsContext *fs_ctx,
> V9fsPath *fs_path,
>  if (fd == -1) {
>  return -1;
>  }
> -do {
> -tsize = read(fd, (void *)buf, bufsz);
> -} while (tsize == -1 && errno == EINTR);
> +TFR(tsize = read(fd, (void *)buf, bufsz));
>  close_preserve_errno(fd);
>  } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
> (fs_ctx->export_flags & V9FS_SM_NONE)) {
> @@ -908,9 +906,7 @@ static int local_symlink(FsContext *fs_ctx, const char
> *oldpath,
>  }
>  /* Write the oldpath (target) to the file. */
>  oldpath_size = strlen(oldpath);
> -do {
> -write_size = write(fd, (void *)oldpath, oldpath_size);
> -} while (write_size == -1 && errno == EINTR);
> +TFR(write_size = write(fd, (void *)oldpath, oldpath_size));
>  close_preserve_errno(fd);
> 
>  if (write_size != oldpath_size) {
> diff --git a/net/l2tpv3.c b/net/l2tpv3.c
> index af373e5c30..adfdbdb84c 100644
> --- a/net/l2tpv3.c
> +++ b/net/l2tpv3.c
> @@ -240,9 +240,7 @@ static ssize_t
> net_l2tpv3_receive_dgram_iov(NetClientState *nc,
>  message.msg_control = NULL;
>  message.msg_controllen = 0;
>  message.msg_flags = 0;
> -do {
> -ret = sendmsg(s->fd, , 0);
> -} while ((ret == -1) && (errno == EINTR));
> +TFR(ret = sendmsg(s->fd, , 0));
>  if (ret > 0) {
>  ret -= s->offset;
>  } else if (ret == 0) {
> @@ -285,9 +283,7 @@ static ssize_t net_l2tpv3_receive_dgram(NetClientState
> *nc,
>  message.msg_control = NULL;
>  message.msg_controllen = 0;
>  message.msg_flags = 0;
> -do {
> -ret = sendmsg(s->fd, , 0);
> -} while ((ret == -1) && (errno == EINTR));
> +TFR(ret = sendmsg(s->fd, , 0));
>  if (ret > 0) {
>  ret -= s->offset;
>  } else if (ret == 0) {
> @@ -434,12 +430,7 @@ static void net_l2tpv3_send(void *opaque)
> 
>  msgvec = s->msgvec + s->queue_head;
>  if (target_count > 0) {
> -do {
> -count = recvmmsg(
> -s->fd,
> -msgvec,
> -target_count, MSG_DONTWAIT, NULL);
> -} while ((count == -1) && (errno == EINTR));
> +TFR(count = recvmmsg(s->fd, msgvec, target_count, MSG_DONTWAIT,
> NULL));
>  if (count < 0) {
>  /* Recv error - we still need to flush packets here,
>   * (re)set queue head to current position
> diff --git a/net/tap.c b/net/tap.c
> index b3ddfd4a74..b047eca8b5 100644
> --- a/net/tap.c
> +++ b/net/tap.c
> @@ -102,9 +102,7 @@ static ssize_t tap_write_packet(TAPState *s, const
> struct iovec *iov, int iovcnt
>  {
>  ssize_t len;
> 
> -do {
> -len = writev(s->fd, iov, iovcnt);
> -} while (len == -1 && errno == EINTR);
> +TFR(len = writev(s->fd, iov, iovcnt));
> 
>  if (len == -1 && errno == EAGAIN) {
>  tap_write_poll(s, t

[PATCH] error handling: Use TFR() macro where applicable

2022-08-04 Thread Nikita Ivanov
>From 0ceb04ada1ed5a863914f4449469d7572d3443ed Mon Sep 17 00:00:00 2001
From: Nikita Ivanov 
Date: Wed, 3 Aug 2022 12:54:00 +0300
Subject: [PATCH] error handling: Use TFR() macro where applicable

There is a defined TFR() macro in qemu/osdep.h which
handles the same while loop.
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/415

Signed-off-by: Nikita Ivanov 
---
 hw/9pfs/9p-local.c   |  8 ++--
 net/l2tpv3.c | 15 +++
 net/tap.c|  8 ++--
 qga/commands-posix.c |  4 +---
 util/main-loop.c |  4 +---
 util/osdep.c |  4 +---
 6 files changed, 10 insertions(+), 33 deletions(-)

diff --git a/hw/9pfs/9p-local.c b/hw/9pfs/9p-local.c
index d42ce6d8b8..c90ab947ba 100644
--- a/hw/9pfs/9p-local.c
+++ b/hw/9pfs/9p-local.c
@@ -470,9 +470,7 @@ static ssize_t local_readlink(FsContext *fs_ctx,
V9fsPath *fs_path,
 if (fd == -1) {
 return -1;
 }
-do {
-tsize = read(fd, (void *)buf, bufsz);
-} while (tsize == -1 && errno == EINTR);
+TFR(tsize = read(fd, (void *)buf, bufsz));
 close_preserve_errno(fd);
 } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
(fs_ctx->export_flags & V9FS_SM_NONE)) {
@@ -908,9 +906,7 @@ static int local_symlink(FsContext *fs_ctx, const char
*oldpath,
 }
 /* Write the oldpath (target) to the file. */
 oldpath_size = strlen(oldpath);
-do {
-write_size = write(fd, (void *)oldpath, oldpath_size);
-} while (write_size == -1 && errno == EINTR);
+TFR(write_size = write(fd, (void *)oldpath, oldpath_size));
 close_preserve_errno(fd);

 if (write_size != oldpath_size) {
diff --git a/net/l2tpv3.c b/net/l2tpv3.c
index af373e5c30..adfdbdb84c 100644
--- a/net/l2tpv3.c
+++ b/net/l2tpv3.c
@@ -240,9 +240,7 @@ static ssize_t
net_l2tpv3_receive_dgram_iov(NetClientState *nc,
 message.msg_control = NULL;
 message.msg_controllen = 0;
 message.msg_flags = 0;
-do {
-ret = sendmsg(s->fd, , 0);
-} while ((ret == -1) && (errno == EINTR));
+TFR(ret = sendmsg(s->fd, , 0));
 if (ret > 0) {
 ret -= s->offset;
 } else if (ret == 0) {
@@ -285,9 +283,7 @@ static ssize_t net_l2tpv3_receive_dgram(NetClientState
*nc,
 message.msg_control = NULL;
 message.msg_controllen = 0;
 message.msg_flags = 0;
-do {
-ret = sendmsg(s->fd, , 0);
-} while ((ret == -1) && (errno == EINTR));
+TFR(ret = sendmsg(s->fd, , 0));
 if (ret > 0) {
 ret -= s->offset;
 } else if (ret == 0) {
@@ -434,12 +430,7 @@ static void net_l2tpv3_send(void *opaque)

 msgvec = s->msgvec + s->queue_head;
 if (target_count > 0) {
-do {
-count = recvmmsg(
-s->fd,
-msgvec,
-target_count, MSG_DONTWAIT, NULL);
-} while ((count == -1) && (errno == EINTR));
+TFR(count = recvmmsg(s->fd, msgvec, target_count, MSG_DONTWAIT,
NULL));
 if (count < 0) {
 /* Recv error - we still need to flush packets here,
  * (re)set queue head to current position
diff --git a/net/tap.c b/net/tap.c
index b3ddfd4a74..b047eca8b5 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -102,9 +102,7 @@ static ssize_t tap_write_packet(TAPState *s, const
struct iovec *iov, int iovcnt
 {
 ssize_t len;

-do {
-len = writev(s->fd, iov, iovcnt);
-} while (len == -1 && errno == EINTR);
+TFR(len = writev(s->fd, iov, iovcnt));

 if (len == -1 && errno == EAGAIN) {
 tap_write_poll(s, true);
@@ -577,9 +575,7 @@ static int net_bridge_run_helper(const char *helper,
const char *bridge,

 close(sv[1]);

-do {
-fd = recv_fd(sv[0]);
-} while (fd == -1 && errno == EINTR);
+TFR(fd = recv_fd(sv[0]));
 saved_errno = errno;

 close(sv[0]);
diff --git a/qga/commands-posix.c b/qga/commands-posix.c
index 954efed01b..90f83aa9b6 100644
--- a/qga/commands-posix.c
+++ b/qga/commands-posix.c
@@ -68,9 +68,7 @@ static void ga_wait_child(pid_t pid, int *status, Error
**errp)

 *status = 0;

-do {
-rpid = waitpid(pid, status, 0);
-} while (rpid == -1 && errno == EINTR);
+TFR(rpid = waitpid(pid, status, 0));

 if (rpid == -1) {
 error_setg_errno(errp, errno, "failed to wait for child (pid: %d)",
diff --git a/util/main-loop.c b/util/main-loop.c
index f00a25451b..58e14db2d4 100644
--- a/util/main-loop.c
+++ b/util/main-loop.c
@@ -64,9 +64,7 @@ static void sigfd_handler(void *opaque)
 ssize_t len;

 while (1) {
-do {
-len = read(fd, , sizeof(info));
-} while (len == -1 && errno == EINTR);
+TFR(len = read(fd, , sizeof(info)));

 if (len == -1 && errno == EAGAIN) {