Commit bf714b27 authored by Neil Schemenauer's avatar Neil Schemenauer

The logreader object did not always refill the input buffer correctly

and got confused by certain log files.  Remove logreader_refill and the
associated logic and replace with fgetc.
parent c60eccb5
...@@ -83,11 +83,8 @@ typedef struct { ...@@ -83,11 +83,8 @@ typedef struct {
PyObject_HEAD PyObject_HEAD
PyObject *info; PyObject *info;
FILE *logfp; FILE *logfp;
int filled;
int index;
int linetimings; int linetimings;
int frametimings; int frametimings;
unsigned char buffer[BUFFERSIZE];
} LogReaderObject; } LogReaderObject;
static PyObject * ProfilerError = NULL; static PyObject * ProfilerError = NULL;
...@@ -272,25 +269,21 @@ logreader_tp_iter(LogReaderObject *self) ...@@ -272,25 +269,21 @@ logreader_tp_iter(LogReaderObject *self)
static int static int
unpack_packed_int(LogReaderObject *self, int *pvalue, int discard) unpack_packed_int(LogReaderObject *self, int *pvalue, int discard)
{ {
int c;
int accum = 0; int accum = 0;
int bits = 0; int bits = 0;
int index = self->index;
int cont; int cont;
do { do {
if (index >= self->filled)
return ERR_EOF;
/* read byte */ /* read byte */
accum |= ((self->buffer[index] & 0x7F) >> discard) << bits; if ((c = fgetc(self->logfp)) == EOF)
return ERR_EOF;
accum |= ((c & 0x7F) >> discard) << bits;
bits += (7 - discard); bits += (7 - discard);
cont = self->buffer[index] & 0x80; cont = c & 0x80;
/* move to next */
discard = 0; discard = 0;
index++;
} while (cont); } while (cont);
/* save state */
self->index = index;
*pvalue = accum; *pvalue = accum;
return 0; return 0;
...@@ -302,43 +295,37 @@ unpack_packed_int(LogReaderObject *self, int *pvalue, int discard) ...@@ -302,43 +295,37 @@ unpack_packed_int(LogReaderObject *self, int *pvalue, int discard)
static int static int
unpack_string(LogReaderObject *self, PyObject **pvalue) unpack_string(LogReaderObject *self, PyObject **pvalue)
{ {
int i;
int len; int len;
int oldindex = self->index; int err;
int err = unpack_packed_int(self, &len, 0); char *buf;
if (!err) { if ((err = unpack_packed_int(self, &len, 0)))
/* need at least len bytes in buffer */ return err;
if (len > (self->filled - self->index)) {
self->index = oldindex; buf = malloc(len);
err = ERR_EOF; for (i=0; i < len; i++) {
} if ((buf[i] = fgetc(self->logfp)) == EOF) {
else { free(buf);
*pvalue = PyString_FromStringAndSize((char *)self->buffer + self->index, return ERR_EOF;
len);
if (*pvalue == NULL) {
self->index = oldindex;
err = ERR_EXCEPTION;
}
else
self->index += len;
} }
} }
return err; *pvalue = PyString_FromStringAndSize(buf, len);
free(buf);
if (*pvalue == NULL) {
return ERR_EXCEPTION;
}
return 0;
} }
static int static int
unpack_add_info(LogReaderObject *self, int skip_opcode) unpack_add_info(LogReaderObject *self)
{ {
PyObject *key; PyObject *key;
PyObject *value = NULL; PyObject *value = NULL;
int err; int err;
if (skip_opcode) {
if (self->buffer[self->index] != WHAT_ADD_INFO)
return ERR_BAD_RECTYPE;
self->index++;
}
err = unpack_string(self, &key); err = unpack_string(self, &key);
if (!err) { if (!err) {
err = unpack_string(self, &value); err = unpack_string(self, &value);
...@@ -368,25 +355,6 @@ unpack_add_info(LogReaderObject *self, int skip_opcode) ...@@ -368,25 +355,6 @@ unpack_add_info(LogReaderObject *self, int skip_opcode)
} }
static void
logreader_refill(LogReaderObject *self)
{
int needed;
size_t res;
if (self->index) {
memmove(self->buffer, &self->buffer[self->index],
self->filled - self->index);
self->filled = self->filled - self->index;
self->index = 0;
}
needed = BUFFERSIZE - self->filled;
if (needed > 0) {
res = fread(&self->buffer[self->filled], 1, needed, self->logfp);
self->filled += res;
}
}
static void static void
eof_error(void) eof_error(void)
{ {
...@@ -397,7 +365,8 @@ eof_error(void) ...@@ -397,7 +365,8 @@ eof_error(void)
static PyObject * static PyObject *
logreader_tp_iternext(LogReaderObject *self) logreader_tp_iternext(LogReaderObject *self)
{ {
int what, oldindex; int c;
int what;
int err = ERR_NONE; int err = ERR_NONE;
int lineno = -1; int lineno = -1;
int fileno = -1; int fileno = -1;
...@@ -413,22 +382,18 @@ logreader_tp_iternext(LogReaderObject *self) ...@@ -413,22 +382,18 @@ logreader_tp_iternext(LogReaderObject *self)
"cannot iterate over closed LogReader object"); "cannot iterate over closed LogReader object");
return NULL; return NULL;
} }
restart:
if ((self->filled - self->index) < MAXEVENTSIZE)
logreader_refill(self);
/* end of input */ restart:
if (self->filled == 0) /* decode the record type */
if ((c = fgetc(self->logfp)) == EOF)
return NULL; return NULL;
oldindex = self->index; what = c & WHAT_OTHER;
if (what == WHAT_OTHER)
what = c; /* need all the bits for type */
else
ungetc(c, self->logfp); /* type byte includes packed int */
/* decode the record type */
what = self->buffer[self->index] & WHAT_OTHER;
if (what == WHAT_OTHER) {
what = self->buffer[self->index];
self->index++;
}
switch (what) { switch (what) {
case WHAT_ENTER: case WHAT_ENTER:
err = unpack_packed_int(self, &fileno, 2); err = unpack_packed_int(self, &fileno, 2);
...@@ -447,7 +412,7 @@ logreader_tp_iternext(LogReaderObject *self) ...@@ -447,7 +412,7 @@ logreader_tp_iternext(LogReaderObject *self)
err = unpack_packed_int(self, &tdelta, 0); err = unpack_packed_int(self, &tdelta, 0);
break; break;
case WHAT_ADD_INFO: case WHAT_ADD_INFO:
err = unpack_add_info(self, 0); err = unpack_add_info(self);
break; break;
case WHAT_DEFINE_FILE: case WHAT_DEFINE_FILE:
err = unpack_packed_int(self, &fileno, 0); err = unpack_packed_int(self, &fileno, 0);
...@@ -468,40 +433,29 @@ logreader_tp_iternext(LogReaderObject *self) ...@@ -468,40 +433,29 @@ logreader_tp_iternext(LogReaderObject *self)
} }
break; break;
case WHAT_LINE_TIMES: case WHAT_LINE_TIMES:
if (self->index >= self->filled) if ((c = fgetc(self->logfp)) == EOF)
err = ERR_EOF; err = ERR_EOF;
else { else {
self->linetimings = self->buffer[self->index] ? 1 : 0; self->linetimings = c ? 1 : 0;
self->index++; goto restart;
goto restart; }
}
break; break;
case WHAT_FRAME_TIMES: case WHAT_FRAME_TIMES:
if (self->index >= self->filled) if ((c = fgetc(self->logfp)) == EOF)
err = ERR_EOF; err = ERR_EOF;
else { else {
self->frametimings = self->buffer[self->index] ? 1 : 0; self->frametimings = c ? 1 : 0;
self->index++; goto restart;
goto restart; }
}
break; break;
default: default:
err = ERR_BAD_RECTYPE; err = ERR_BAD_RECTYPE;
} }
if (err == ERR_EOF && oldindex != 0) {
/* It looks like we ran out of data before we had it all; this
* could easily happen with large packed integers or string
* data. Try forcing the buffer to be re-filled before failing.
*/
err = ERR_NONE;
logreader_refill(self);
}
if (err == ERR_BAD_RECTYPE) { if (err == ERR_BAD_RECTYPE) {
PyErr_SetString(PyExc_ValueError, PyErr_SetString(PyExc_ValueError,
"unknown record type in log file"); "unknown record type in log file");
} }
else if (err == ERR_EOF) { else if (err == ERR_EOF) {
/* Could not avoid end-of-buffer error. */
eof_error(); eof_error();
} }
else if (!err) { else if (!err) {
...@@ -1389,12 +1343,12 @@ hotshot_logreader(PyObject *unused, PyObject *args) ...@@ -1389,12 +1343,12 @@ hotshot_logreader(PyObject *unused, PyObject *args)
{ {
LogReaderObject *self = NULL; LogReaderObject *self = NULL;
char *filename; char *filename;
int c;
int err = 0;
if (PyArg_ParseTuple(args, "s:logreader", &filename)) { if (PyArg_ParseTuple(args, "s:logreader", &filename)) {
self = PyObject_New(LogReaderObject, &LogReaderType); self = PyObject_New(LogReaderObject, &LogReaderType);
if (self != NULL) { if (self != NULL) {
self->filled = 0;
self->index = 0;
self->frametimings = 1; self->frametimings = 1;
self->linetimings = 0; self->linetimings = 0;
self->info = NULL; self->info = NULL;
...@@ -1410,14 +1364,17 @@ hotshot_logreader(PyObject *unused, PyObject *args) ...@@ -1410,14 +1364,17 @@ hotshot_logreader(PyObject *unused, PyObject *args)
Py_DECREF(self); Py_DECREF(self);
goto finally; goto finally;
} }
/* Aggressively attempt to load all preliminary ADD_INFO /* read initial info */
* records from the log so the info records are available for (;;) {
* from a fresh logreader object. if ((c = fgetc(self->logfp)) == EOF) {
*/ eof_error();
logreader_refill(self); break;
while (self->filled > self->index }
&& self->buffer[self->index] == WHAT_ADD_INFO) { if (c != WHAT_ADD_INFO) {
int err = unpack_add_info(self, 1); ungetc(c, self->logfp);
break;
}
err = unpack_add_info(self);
if (err) { if (err) {
if (err == ERR_EOF) if (err == ERR_EOF)
eof_error(); eof_error();
...@@ -1426,12 +1383,6 @@ hotshot_logreader(PyObject *unused, PyObject *args) ...@@ -1426,12 +1383,6 @@ hotshot_logreader(PyObject *unused, PyObject *args)
"unexpected error"); "unexpected error");
break; break;
} }
/* Refill agressively so we can avoid EOF during
* initialization unless there's a real EOF condition
* (the tp_iternext handler loops attempts to refill
* and try again).
*/
logreader_refill(self);
} }
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment