Skip to content

Commit 7dd16b6

Browse files
committed
Flush buffers before reading in addresses
1 parent e4e99e5 commit 7dd16b6

File tree

4 files changed

+54
-17
lines changed

4 files changed

+54
-17
lines changed

src/_vmprof.c

+20-1
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,23 @@ start_sampling(PyObject *module, PyObject *noargs)
363363
Py_RETURN_NONE;
364364
}
365365

366+
static PyObject *
367+
vmp_flush_buffers(PyObject *module, PyObject *noargs)
368+
{
369+
int ret = 0;
370+
371+
#ifdef VMPROF_UNIX
372+
ret = flush_buffers(vmp_profile_fileno());
373+
if (ret != 0) {
374+
return PyLong_NEW(ret);
375+
}
376+
377+
ret = fsync(fd);
378+
#endif
379+
380+
return PyLong_NEW(ret);
381+
}
382+
366383
#ifdef VMPROF_UNIX
367384
static PyObject * vmp_get_profile_path(PyObject *module, PyObject *noargs) {
368385
PyObject * o;
@@ -437,7 +454,9 @@ static PyMethodDef VMProfMethods[] = {
437454
{"stop_sampling", stop_sampling, METH_NOARGS,
438455
"Blocks signals to occur and returns the file descriptor"},
439456
{"start_sampling", start_sampling, METH_NOARGS,
440-
"Unblocks vmprof signals. After compeltion vmprof will sample again"},
457+
"Unblocks vmprof signals. After completion vmprof will sample again"},
458+
{"flush_buffers", vmp_flush_buffers, METH_NOARGS,
459+
"Flushes all pending buffers to the file descriptor"},
441460
#ifdef VMP_SUPPORTS_NATIVE_PROFILING
442461
{"resolve_addr", resolve_addr, METH_VARARGS,
443462
"Returns the name of the given address"},

src/vmprof_mt.c

+25-7
Original file line numberDiff line numberDiff line change
@@ -161,21 +161,39 @@ void cancel_buffer(struct profbuf_s *buf)
161161
profbuf_state[i] = PROFBUF_UNUSED;
162162
}
163163

164-
int shutdown_concurrent_bufs(int fd)
164+
int flush_buffers(int fd)
165165
{
166-
/* no signal handler can be running concurrently here, because we
167-
already did vmprof_ignore_signals(1) */
168-
assert(profbuf_write_lock == 0);
169-
profbuf_write_lock = 2;
166+
if (!__sync_bool_compare_and_swap(&profbuf_write_lock, 0, 1)) {
167+
return -1;
168+
}
170169

171-
/* last attempt to flush buffers */
172170
int i;
173171
for (i = 0; i < MAX_NUM_BUFFERS; i++) {
174172
while (profbuf_state[i] == PROFBUF_READY) {
175-
if (_write_single_ready_buffer(fd, i) < 0)
173+
if (_write_single_ready_buffer(fd, i) < 0) {
174+
profbuf_write_lock = 0;
176175
return -1;
176+
}
177177
}
178178
}
179+
180+
profbuf_write_lock = 0;
181+
return 0;
182+
}
183+
184+
int shutdown_concurrent_bufs(int fd)
185+
{
186+
/* no signal handler can be running concurrently here, because we
187+
already did vmprof_ignore_signals(1) */
188+
assert(profbuf_write_lock == 0);
189+
190+
/* last attempt to flush buffers */
191+
int flushed = flush_buffers(fd);
192+
if (flushed != 0) {
193+
return flushed;
194+
}
195+
196+
profbuf_write_lock = 2;
179197
unprepare_concurrent_bufs();
180198
return 0;
181199
}

src/vmprof_mt.h

+1
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,5 @@ int prepare_concurrent_bufs(void);
4848
struct profbuf_s *reserve_buffer(int fd);
4949
void commit_buffer(int fd, struct profbuf_s *buf);
5050
void cancel_buffer(struct profbuf_s *buf);
51+
int flush_buffers(int fd);
5152
int shutdown_concurrent_bufs(int fd);

vmprof/__init__.py

+8-9
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,14 @@
2929
def disable():
3030
try:
3131
# fish the file descriptor that is still open!
32-
if hasattr(_vmprof, 'stop_sampling'):
33-
fileno = _vmprof.stop_sampling()
34-
if fileno >= 0:
35-
# TODO does fileobj leak the fd? I dont think so, but need to check
36-
fileobj = FdWrapper(fileno)
37-
l = LogReaderDumpNative(fileobj, LogReaderState())
38-
l.read_all()
39-
if hasattr(_vmprof, 'write_all_code_objects'):
40-
_vmprof.write_all_code_objects(l.dedup)
32+
fileno = _vmprof.stop_sampling()
33+
if fileno >= 0:
34+
_vmprof.flush_buffers()
35+
# TODO does fileobj leak the fd? I dont think so, but need to check
36+
fileobj = FdWrapper(fileno)
37+
l = LogReaderDumpNative(fileobj, LogReaderState())
38+
l.read_all()
39+
_vmprof.write_all_code_objects(l.dedup)
4140
_vmprof.disable()
4241
except IOError as e:
4342
raise Exception("Error while writing profile: " + str(e))

0 commit comments

Comments
 (0)