Skip to content

Commit

Permalink
Do not crash sometimes when parsing /sys for network throughput
Browse files Browse the repository at this point in the history
Two examples of the bugs seen are below which cause the program to exit.
Handle them by moving to regular C file handling, which I preferred over
wrapping in exceptions as the error cases and releasing of resources is
clearer; elsewhere in the project we have considered them better for parsing
/sys and /proc information.

It looks like there is code here that parses /proc, and is most likely
redundant because users are unlikely to be on an old enough kernel to
require this; I imagine everyone has /sys mounted and we the codebase
probably won't build on the old compilers that would be required on such
systems.

  $ xosview
  Can not open file : /sys/class/net/tap0/statistics/rx_bytes

  $ xosview
  terminate called after throwing an instance of 'std::ios_base::failure'
    what():  basic_filebuf::underflow error reading the file
  Abort (core dumped)

  (gdb) bt
  #0  0x000000320a0325e5 in raise () from /lib64/libc.so.6
  #1  0x000000320a033dc5 in abort () from /lib64/libc.so.6
  #2  0x000000320f8bea7d in __gnu_cxx::__verbose_terminate_handler() () from /usr/lib64/libstdc++.so.6
  #3  0x000000320f8bcbd6 in ?? () from /usr/lib64/libstdc++.so.6
  #4  0x000000320f8bcc03 in std::terminate() () from /usr/lib64/libstdc++.so.6
  #5  0x000000320f8bcd22 in __cxa_throw () from /usr/lib64/libstdc++.so.6
  #6  0x000000320f8619da in std::__throw_ios_failure(char const*) () from /usr/lib64/libstdc++.so.6
  #7  0x000000320f87172a in std::basic_filebuf<char, std::char_traits<char> >::underflow() () from /usr/lib64/libstdc++.so.6
  #8  0x000000320f87809b in std::basic_istream<char, std::char_traits<char> >::sentry::sentry(std::basic_istream<char, std::char_traits<char> >&, bool) () from /usr/lib64/libstdc++.so.6
  #9  0x000000320f87860b in std::basic_istream<char, std::char_traits<char> >& std::basic_istream<char, std::char_traits<char> >::_M_extract<unsigned long long>(unsigned long long&) () from /usr/lib64/libstdc++.so.6
  #10 0x00000000004215a7 in NetMeter::getSysStats(unsigned long long&, unsigned long long&) ()
  #11 0x000000000042197a in NetMeter::checkevent() ()
  #12 0x000000000040c390 in XOSView::run() ()
  #13 0x000000000040b5a1 in main ()
  • Loading branch information
hills committed Nov 4, 2017
1 parent f7ecc7d commit acef3cd
Showing 1 changed file with 29 additions and 21 deletions.
50 changes: 29 additions & 21 deletions linux/netmeter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,33 @@
static const char PROCNETDEV[] = "/proc/net/dev";
static const char SYSCLASSNET[] = "/sys/class/net";

/*
* Parse the integer count from the given filename
*
* This is quite relaxed about error conditions because the file may
* have been removed before it was opened, or truncated, in which case
* the count is zero.
*
* Return: 0 if not not avilable, otherwise count (which may be zero)
*/

static unsigned long long getCount( const char *filename ){
unsigned long long n, count = 0;
FILE *f;

f = fopen(filename, "r");
if (!f)
return 0;

if (fscanf(f, "%llu", &n) == 1)
count = n;

if (fclose(f) != 0)
abort();

return count;
}


NetMeter::NetMeter( XOSView *parent, float max )
: FieldMeterGraph( parent, 3, "NET", "IN/OUT/IDLE" ){
Expand Down Expand Up @@ -94,7 +121,6 @@ void NetMeter::getSysStats( unsigned long long &totin, unsigned long long &totou
struct dirent *ent;
char filename[128];
std::ifstream ifs;
unsigned long long value;

if ( !(dir = opendir(SYSCLASSNET)) ) {
std::cerr << "Can not open directory : " << SYSCLASSNET << std::endl;
Expand All @@ -112,28 +138,10 @@ void NetMeter::getSysStats( unsigned long long &totin, unsigned long long &totou
continue;

snprintf(filename, 128, "%s/%s/statistics/rx_bytes", SYSCLASSNET, ent->d_name);
ifs.open(filename);
if ( !ifs.good() ) {
std::cerr << "Can not open file : " << filename << std::endl;
parent_->done(1);
return;
}
ifs >> value;
ifs.close();
totin += value;
XOSDEBUG("%s: %llu bytes received", ent->d_name, value);
totin += getCount(filename);

snprintf(filename, 128, "%s/%s/statistics/tx_bytes", SYSCLASSNET, ent->d_name);
ifs.open(filename);
if ( !ifs.good() ) {
std::cerr << "Can not open file : " << filename << std::endl;
parent_->done(1);
return;
}
ifs >> value;
ifs.close();
totout += value;
XOSDEBUG(", %llu bytes sent.\n", value);
totout += getCount(filename);
}
closedir(dir);
}
Expand Down

0 comments on commit acef3cd

Please sign in to comment.