Message ID | 20240307103847.3710737-1-xin.wang2@amd.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [v2] tools/9pfsd: Fix build error caused by strerror_r() | expand |
On 07.03.24 11:38, Henry Wang wrote: > Below error can be seen when doing Yocto build of the toolstack: > > | io.c: In function 'p9_error': > | io.c:684:5: error: ignoring return value of 'strerror_r' declared > with attribute 'warn_unused_result' [-Werror=unused-result] > | 684 | strerror_r(err, ring->buffer, ring->ring_size); > | | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > | cc1: all warnings being treated as errors > > Fix the build by using strerror() to replace strerror_r(). Since > strerror() is thread-unsafe, use a separate local mutex to protect > the action. The steps would then become: Acquire the mutex first, > invoke strerror(), copy the string from strerror() to the designated > buffer and then drop the mutex. > > Signed-off-by: Henry Wang <xin.wang2@amd.com> Maybe add a "Fixes:" tag referencing Jan's patch? And I would expand on the reason why you are using strerror() instead of just checking the strerror_r() result. Something like: Using strerror_r() without special casing different build environments is impossible due to the different return types (int vs char *) depending on the environment. As p9_error() is not on a performance critical path, using strerror() with a mutex ought to be fine. > --- > tools/9pfsd/io.c | 12 +++++++++++- > 1 file changed, 11 insertions(+), 1 deletion(-) > > diff --git a/tools/9pfsd/io.c b/tools/9pfsd/io.c > index adb887c7d9..2b80c9528d 100644 > --- a/tools/9pfsd/io.c > +++ b/tools/9pfsd/io.c > @@ -680,8 +680,18 @@ static bool name_ok(const char *str) > static void p9_error(struct ring *ring, uint16_t tag, uint32_t err) > { > unsigned int erroff; > + static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; > + char *strerror_str; > + RING_IDX strerror_len = 0, copy_len = 0; I wouldn't use RING_IDX for the type, but unsigned int. > + > + pthread_mutex_lock(&mutex); > + strerror_str = strerror(err); > + strerror_len = strlen(strerror_str) + 1; > + copy_len = min(strerror_len, ring->ring_size); > + memcpy(ring->buffer, strerror_str, copy_len); > + ((char *)(ring->buffer))[copy_len - 1] = '\0'; > + pthread_mutex_unlock(&mutex); > > - strerror_r(err, ring->buffer, ring->ring_size); > erroff = add_string(ring, ring->buffer, strlen(ring->buffer)); > fill_buffer(ring, P9_CMD_ERROR, tag, "SU", > erroff != ~0 ? ring->str + erroff : "cannot allocate memory", Juergen
On 07.03.2024 11:38, Henry Wang wrote: > Below error can be seen when doing Yocto build of the toolstack: > > | io.c: In function 'p9_error': > | io.c:684:5: error: ignoring return value of 'strerror_r' declared > with attribute 'warn_unused_result' [-Werror=unused-result] > | 684 | strerror_r(err, ring->buffer, ring->ring_size); > | | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > | cc1: all warnings being treated as errors > > Fix the build by using strerror() to replace strerror_r(). Since > strerror() is thread-unsafe, use a separate local mutex to protect > the action. The steps would then become: Acquire the mutex first, > invoke strerror(), copy the string from strerror() to the designated > buffer and then drop the mutex. > Fixes: f4900d6d69b5 ("9pfsd: allow building with old glibc") > Signed-off-by: Henry Wang <xin.wang2@amd.com> Reviewed-by: Jan Beulich <jbeulich@suse.com> albeit there are a number of cosmetic aspects I'd have done differently (see bottom of mail). The one thing I'd really like to ask for it a comment ... > --- a/tools/9pfsd/io.c > +++ b/tools/9pfsd/io.c > @@ -680,8 +680,18 @@ static bool name_ok(const char *str) > static void p9_error(struct ring *ring, uint16_t tag, uint32_t err) > { > unsigned int erroff; > + static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; > + char *strerror_str; > + RING_IDX strerror_len = 0, copy_len = 0; > + ... here explaining why strerror_r() isn't used. Unless other comments arise and a v3 would be needed, I'd add /* * While strerror_r() exists, it comes in a POSIX and a GNU flavor. * Let's try to avoid trying to be clever with determining which * one it is that the underlying C library offers, when really we * don't expect this function to be called very often. */ while committing. Anyway it'll need a maintainer ack first. > + pthread_mutex_lock(&mutex); > + strerror_str = strerror(err); > + strerror_len = strlen(strerror_str) + 1; > + copy_len = min(strerror_len, ring->ring_size); > + memcpy(ring->buffer, strerror_str, copy_len); > + ((char *)(ring->buffer))[copy_len - 1] = '\0'; > + pthread_mutex_unlock(&mutex); > > - strerror_r(err, ring->buffer, ring->ring_size); > erroff = add_string(ring, ring->buffer, strlen(ring->buffer)); > fill_buffer(ring, P9_CMD_ERROR, tag, "SU", > erroff != ~0 ? ring->str + erroff : "cannot allocate memory", pthread_mutex_lock(&mutex); str = strerror(err); len = min(strlen(str), ring->ring_size - 1); memcpy(ring->buffer, str, len); ((char *)ring->buffer)[len] = '\0'; pthread_mutex_unlock(&mutex); Jan
On 07.03.24 11:38, Henry Wang wrote: > Below error can be seen when doing Yocto build of the toolstack: > > | io.c: In function 'p9_error': > | io.c:684:5: error: ignoring return value of 'strerror_r' declared > with attribute 'warn_unused_result' [-Werror=unused-result] > | 684 | strerror_r(err, ring->buffer, ring->ring_size); > | | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > | cc1: all warnings being treated as errors > > Fix the build by using strerror() to replace strerror_r(). Since > strerror() is thread-unsafe, use a separate local mutex to protect > the action. The steps would then become: Acquire the mutex first, > invoke strerror(), copy the string from strerror() to the designated > buffer and then drop the mutex. > > Signed-off-by: Henry Wang <xin.wang2@amd.com> > --- > tools/9pfsd/io.c | 12 +++++++++++- > 1 file changed, 11 insertions(+), 1 deletion(-) > > diff --git a/tools/9pfsd/io.c b/tools/9pfsd/io.c > index adb887c7d9..2b80c9528d 100644 > --- a/tools/9pfsd/io.c > +++ b/tools/9pfsd/io.c > @@ -680,8 +680,18 @@ static bool name_ok(const char *str) > static void p9_error(struct ring *ring, uint16_t tag, uint32_t err) > { > unsigned int erroff; > + static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; > + char *strerror_str; > + RING_IDX strerror_len = 0, copy_len = 0; > + > + pthread_mutex_lock(&mutex); > + strerror_str = strerror(err); > + strerror_len = strlen(strerror_str) + 1; > + copy_len = min(strerror_len, ring->ring_size); Hmm, I think we even _need_ to cap the string earlier. A string in the 9pfs protocol is a 2 byte length field plus the string. In case of a ring larger than 65535 bytes this would mean the result of strerror() could (in theory) overflow the string format of 9pfs. Additionally the string should be a _short_ description of the error, so I'd like to suggest to not use ring_size as the upper bound for the string length, but a fixed value defined as a macro, e.g.: #define MAX_ERRSTR_LEN 80 Juergen
Hi Jan, On 3/7/2024 7:04 PM, Jan Beulich wrote: > On 07.03.2024 11:38, Henry Wang wrote: >> Below error can be seen when doing Yocto build of the toolstack: >> >> | io.c: In function 'p9_error': >> | io.c:684:5: error: ignoring return value of 'strerror_r' declared >> with attribute 'warn_unused_result' [-Werror=unused-result] >> | 684 | strerror_r(err, ring->buffer, ring->ring_size); >> | | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ >> | cc1: all warnings being treated as errors >> >> Fix the build by using strerror() to replace strerror_r(). Since >> strerror() is thread-unsafe, use a separate local mutex to protect >> the action. The steps would then become: Acquire the mutex first, >> invoke strerror(), copy the string from strerror() to the designated >> buffer and then drop the mutex. >> >> >> Fixes: f4900d6d69b5 ("9pfsd: allow building with old glibc") I will add this tag in v3. >> Signed-off-by: Henry Wang <xin.wang2@amd.com> > Reviewed-by: Jan Beulich <jbeulich@suse.com> Thanks! > albeit there are a number of cosmetic aspects I'd have done differently > (see bottom of mail). The one thing I'd really like to ask for it a > comment ... > >> --- a/tools/9pfsd/io.c >> +++ b/tools/9pfsd/io.c >> @@ -680,8 +680,18 @@ static bool name_ok(const char *str) >> static void p9_error(struct ring *ring, uint16_t tag, uint32_t err) >> { >> unsigned int erroff; >> + static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; >> + char *strerror_str; >> + RING_IDX strerror_len = 0, copy_len = 0; >> + > ... here explaining why strerror_r() isn't used. Unless other comments > arise and a v3 would be needed, I'd add > > /* > * While strerror_r() exists, it comes in a POSIX and a GNU flavor. > * Let's try to avoid trying to be clever with determining which > * one it is that the underlying C library offers, when really we > * don't expect this function to be called very often. > */ > > while committing. Since I am working on a V3 which will be sent out soon, please don't bother :) I will handle it from my side. > Anyway it'll need a maintainer ack first. > >> + pthread_mutex_lock(&mutex); >> + strerror_str = strerror(err); >> + strerror_len = strlen(strerror_str) + 1; >> + copy_len = min(strerror_len, ring->ring_size); >> + memcpy(ring->buffer, strerror_str, copy_len); >> + ((char *)(ring->buffer))[copy_len - 1] = '\0'; >> + pthread_mutex_unlock(&mutex); >> >> - strerror_r(err, ring->buffer, ring->ring_size); >> erroff = add_string(ring, ring->buffer, strlen(ring->buffer)); >> fill_buffer(ring, P9_CMD_ERROR, tag, "SU", >> erroff != ~0 ? ring->str + erroff : "cannot allocate memory", > pthread_mutex_lock(&mutex); > str = strerror(err); > len = min(strlen(str), ring->ring_size - 1); This actually will fire below errors on my build env, hence I separated them with a different variable. tools/include/xen-tools/common-macros.h:38:21: error: comparison of distinct pointer types lacks a cast [-Werror] | 38 | (void) (&_x == &_y); \ | | ^~ | io.c:695:11: note: in expansion of macro 'min' | 695 | len = min(strlen(str), MAX_ERRSTR_LEN - 1);; | | ^~~ | cc1: all warnings being treated as errors > memcpy(ring->buffer, str, len); > ((char *)ring->buffer)[len] = '\0'; > pthread_mutex_unlock(&mutex); I will follow your style in V3 if you don't have any specific comment on the error that I posted above (plus also not strongly disagree with my approach in v2). Kind regards, Henry > Jan
Hi Juergen, On 3/7/2024 6:51 PM, Juergen Gross wrote: > On 07.03.24 11:38, Henry Wang wrote: >> Below error can be seen when doing Yocto build of the toolstack: >> >> | io.c: In function 'p9_error': >> | io.c:684:5: error: ignoring return value of 'strerror_r' declared >> with attribute 'warn_unused_result' [-Werror=unused-result] >> | 684 | strerror_r(err, ring->buffer, ring->ring_size); >> | | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ >> | cc1: all warnings being treated as errors >> >> Fix the build by using strerror() to replace strerror_r(). Since >> strerror() is thread-unsafe, use a separate local mutex to protect >> the action. The steps would then become: Acquire the mutex first, >> invoke strerror(), copy the string from strerror() to the designated >> buffer and then drop the mutex. >> >> Signed-off-by: Henry Wang <xin.wang2@amd.com> > > Maybe add a "Fixes:" tag referencing Jan's patch? Yes, will do. > And I would expand on the reason why you are using strerror() instead > of just > checking the strerror_r() result. Something like: > > Using strerror_r() without special casing different build > environments is impossible due to the different return types > (int vs char *) depending on the environment. As p9_error() > is not on a performance critical path, using strerror() with a > mutex ought to be fine. Thanks! Will add in commit message. >> --- >> tools/9pfsd/io.c | 12 +++++++++++- >> 1 file changed, 11 insertions(+), 1 deletion(-) >> >> diff --git a/tools/9pfsd/io.c b/tools/9pfsd/io.c >> index adb887c7d9..2b80c9528d 100644 >> --- a/tools/9pfsd/io.c >> +++ b/tools/9pfsd/io.c >> @@ -680,8 +680,18 @@ static bool name_ok(const char *str) >> static void p9_error(struct ring *ring, uint16_t tag, uint32_t err) >> { >> unsigned int erroff; >> + static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; >> + char *strerror_str; >> + RING_IDX strerror_len = 0, copy_len = 0; > > I wouldn't use RING_IDX for the type, but unsigned int. Ok, I just mainly wanted to keep some consistency, but yeah unsigned int is definitely ok. Will follow your suggestion. Kind regards, Henry
Hi Juergen, On 3/7/2024 7:24 PM, Juergen Gross wrote: > On 07.03.24 11:38, Henry Wang wrote: >> Below error can be seen when doing Yocto build of the toolstack: >> >> | io.c: In function 'p9_error': >> | io.c:684:5: error: ignoring return value of 'strerror_r' declared >> with attribute 'warn_unused_result' [-Werror=unused-result] >> | 684 | strerror_r(err, ring->buffer, ring->ring_size); >> | | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ >> | cc1: all warnings being treated as errors >> >> Fix the build by using strerror() to replace strerror_r(). Since >> strerror() is thread-unsafe, use a separate local mutex to protect >> the action. The steps would then become: Acquire the mutex first, >> invoke strerror(), copy the string from strerror() to the designated >> buffer and then drop the mutex. >> >> Signed-off-by: Henry Wang <xin.wang2@amd.com> >> --- >> tools/9pfsd/io.c | 12 +++++++++++- >> 1 file changed, 11 insertions(+), 1 deletion(-) >> >> diff --git a/tools/9pfsd/io.c b/tools/9pfsd/io.c >> index adb887c7d9..2b80c9528d 100644 >> --- a/tools/9pfsd/io.c >> +++ b/tools/9pfsd/io.c >> @@ -680,8 +680,18 @@ static bool name_ok(const char *str) >> static void p9_error(struct ring *ring, uint16_t tag, uint32_t err) >> { >> unsigned int erroff; >> + static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; >> + char *strerror_str; >> + RING_IDX strerror_len = 0, copy_len = 0; >> + >> + pthread_mutex_lock(&mutex); >> + strerror_str = strerror(err); >> + strerror_len = strlen(strerror_str) + 1; >> + copy_len = min(strerror_len, ring->ring_size); > > Hmm, I think we even _need_ to cap the string earlier. > > A string in the 9pfs protocol is a 2 byte length field plus the string. > In case of a ring larger than 65535 bytes this would mean the result of > strerror() could (in theory) overflow the string format of 9pfs. > > Additionally the string should be a _short_ description of the error, so > I'd like to suggest to not use ring_size as the upper bound for the > string > length, but a fixed value defined as a macro, e.g.: > > #define MAX_ERRSTR_LEN 80 I can use a macro-defined value in v3, sure. Kind regards, Henry > Juergen
On 3/7/2024 8:19 PM, Henry Wang wrote: >> len = min(strlen(str), ring->ring_size - 1); > > This actually will fire below errors on my build env, hence I > separated them with a different variable. > > tools/include/xen-tools/common-macros.h:38:21: error: comparison of > distinct pointer types lacks a cast [-Werror] > | 38 | (void) (&_x == &_y); \ > | | ^~ > | io.c:695:11: note: in expansion of macro 'min' > | 695 | len = min(strlen(str), MAX_ERRSTR_LEN - 1);; > | | ^~~ > | cc1: all warnings being treated as errors > >> memcpy(ring->buffer, str, len); >> ((char *)ring->buffer)[len] = '\0'; >> pthread_mutex_unlock(&mutex); > > I will follow your style in V3 if you don't have any specific comment > on the error that I posted above (plus also not strongly disagree with > my approach in v2). In fact I think ``` len = min(strlen(str), (size_t)(MAX_ERRSTR_LEN - 1)); ``` is better. Kind regards, Henry > Kind regards, > Henry > >> Jan
diff --git a/tools/9pfsd/io.c b/tools/9pfsd/io.c index adb887c7d9..2b80c9528d 100644 --- a/tools/9pfsd/io.c +++ b/tools/9pfsd/io.c @@ -680,8 +680,18 @@ static bool name_ok(const char *str) static void p9_error(struct ring *ring, uint16_t tag, uint32_t err) { unsigned int erroff; + static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; + char *strerror_str; + RING_IDX strerror_len = 0, copy_len = 0; + + pthread_mutex_lock(&mutex); + strerror_str = strerror(err); + strerror_len = strlen(strerror_str) + 1; + copy_len = min(strerror_len, ring->ring_size); + memcpy(ring->buffer, strerror_str, copy_len); + ((char *)(ring->buffer))[copy_len - 1] = '\0'; + pthread_mutex_unlock(&mutex); - strerror_r(err, ring->buffer, ring->ring_size); erroff = add_string(ring, ring->buffer, strlen(ring->buffer)); fill_buffer(ring, P9_CMD_ERROR, tag, "SU", erroff != ~0 ? ring->str + erroff : "cannot allocate memory",
Below error can be seen when doing Yocto build of the toolstack: | io.c: In function 'p9_error': | io.c:684:5: error: ignoring return value of 'strerror_r' declared with attribute 'warn_unused_result' [-Werror=unused-result] | 684 | strerror_r(err, ring->buffer, ring->ring_size); | | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | cc1: all warnings being treated as errors Fix the build by using strerror() to replace strerror_r(). Since strerror() is thread-unsafe, use a separate local mutex to protect the action. The steps would then become: Acquire the mutex first, invoke strerror(), copy the string from strerror() to the designated buffer and then drop the mutex. Signed-off-by: Henry Wang <xin.wang2@amd.com> --- tools/9pfsd/io.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-)