Skip to content
This repository has been archived by the owner on Jan 26, 2019. It is now read-only.

Improve error messages #84

Merged
merged 3 commits into from
Nov 22, 2017
Merged

Improve error messages #84

merged 3 commits into from
Nov 22, 2017

Conversation

oschwald
Copy link
Member

@oschwald oschwald commented Nov 21, 2017

Closes #82

Also, fixed some incorrect error checking. There are likely many other
places where the error checking needs to be improved. I only fixed
issues that I noticed when trying to improve the existing messages.

Closes #82.
Copy link
Contributor

@horgh horgh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A good step forward!

I've mostly got questions around whether errno is set in a few cases!

@@ -74,7 +73,7 @@ static void xasprintf(char **ptr, const char *fmt, ...) {
va_start(ap, fmt);
int rc = vasprintf(ptr, fmt, ap);
va_end(ap);
exit_if(rc == -1, "Out of memory\n");
exit_if(rc == -1, "Error calling vasprintf: %s\n", strerror(errno));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, will vasprintf() actually set errno? Normally I'd go by what the man page says and I don't see it saying it does for this function.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All of the POSIX printf functions set errno:

http://pubs.opengroup.org/onlinepubs/9699919799/functions/fprintf.html

For vasprintf(), I checked both FreeBSD and glibc. Both set it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Much better docs than the man page. I'll have to remember to look there.

I don't think this one is POSIX, is it? It sounds like it's okay to expect it be set anyway though.

void *xmalloc(size_t size) {
void *ptr = malloc(size);
exit_if(!ptr, "Out of memory\n");
exit_if(!ptr, "Error allocating memory: %s\n", strerror(errno));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we were to be very pedantic, I'm not sure we can guarantee calloc() will set errno. C99 doesn't require it, at least. Maybe this is ugly, but in the past I've just done strerror(ENOMEM) for such cases. It looks like there are some existing cases of this as well.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In all modern Unixes, this should be set properly. I double checked on Windows and it appears it gets set there too.

From the calloc man page:

   SUSv2 requires malloc(), calloc(), and realloc() to set errno to ENOMEM upon failure.  Glibc assumes that this is done (and the glibc versions
   of these routines do this); if you use a private malloc implementation that does not set errno, then certain library routines may fail without
   having a reason in errno.

Is there a particular implementation that you are concerned about?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, I mainly went by what you pasted and it not being specified in the standard.

Copy link
Contributor

@horgh horgh Nov 22, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have the same situation where POSIX says it should be set, so that's another point in favour of using errno!

return ptr;
}

static void *xrealloc(void *ptr, size_t size) {
void *mem = realloc(ptr, size);
exit_if(mem == NULL, "Out of memory\n");
exit_if(mem == NULL, "Error reallocating memory: %s\n", strerror(errno));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My comment about calloc() applies to realloc()


md5_init(&context);
while ((len = fread(buffer, 1, bsize, fh)) > 0) {
md5_write(&context, buffer, len);
}
exit_if(ferror(fh), "Unable to read %s: %s\n", fname, strerror(errno));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, this is another case I'm not sure we get errno set.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh good.

md5_final(&context);
memcpy(digest, context.buf, 16);
exit_if(-1 == fclose(fh), "Error closing stream: %s", strerror(errno));
for (int i = 0; i < 16; i++) {
snprintf(&hex_digest[2 * i], 3, "%02x", digest[i]);
int c = snprintf(&hex_digest[2 * i], 3, "%02x", digest[i]);
exit_if(c < 0, "Unable to write digest: %s\n", strerror(errno));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Likewise, does snprintf() set errno?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See above.

"Gzip write error\n");
"Unable to write to %s: %s\n",
file_path_test,
strerror(errno));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think fwrite() will set errno

file_path_test,
strerror(errno));
}
exit_if(-1 == fclose(fhw), "Error closing stream: %s\n", strerror(errno));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting, the docs say fclose() does set errno. At least there is consistency!

#include <stdlib.h>
#include <string.h>

geoipupdate_s *geoipupdate_s_new(void) {
size_t size = sizeof(geoipupdate_s);
geoipupdate_s *gu = xmalloc(size);
geoipupdate_s *gu = xcalloc(1, size);
memset(gu, 0, size);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't need to memset now I think

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! I missed that.

@horgh
Copy link
Contributor

horgh commented Nov 22, 2017

I'm happy to merge it. I'm just going to wait on the Travis build.

@horgh horgh merged commit 4420238 into master Nov 22, 2017
@horgh horgh deleted the greg/better-error-messages branch November 22, 2017 01:14
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Development

Successfully merging this pull request may close these issues.

2 participants