Skip to content

Commit

Permalink
Fix SEGFAULT if IO struct is allocated not by the lcb_create()
Browse files Browse the repository at this point in the history
Change-Id: Id40ad6a54ad78a22eb7b68560370c3045758320e
Reviewed-on: http://review.couchbase.org/21439
Tested-by: Sergey Avseyev <sergey.avseyev@gmail.com>
Reviewed-by: Trond Norbye <trond.norbye@gmail.com>
  • Loading branch information
avsej authored and trondn committed Oct 10, 2012
1 parent 21e2fa8 commit a1b17df
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 14 deletions.
8 changes: 8 additions & 0 deletions include/libcouchbase/couchbase.h
Expand Up @@ -62,6 +62,14 @@ extern "C" {
lcb_error_t lcb_create_io_ops(lcb_io_opt_t *op,
const struct lcb_create_io_ops_st *options);

/**
* Destory io ops instance.
* @param op ops structure
* @return LCB_SUCCESS on success
*/
LIBCOUCHBASE_API
lcb_error_t lcb_destroy_io_ops(lcb_io_opt_t op);

/**
* Create an instance of lcb.
*
Expand Down
1 change: 1 addition & 0 deletions include/libcouchbase/types.h
Expand Up @@ -247,6 +247,7 @@ extern "C" {
void *cookie;
int error;
void *dlhandle;
int need_cleanup;

void (*destructor)(struct lcb_io_opt_st *iops);

Expand Down
3 changes: 3 additions & 0 deletions plugins/io/libev/plugin-libev.c
Expand Up @@ -351,6 +351,9 @@ lcb_error_t lcb_create_libev_io_opts(lcb_io_opt_t *io, struct ev_loop *loop)
/* setup io iops! */
ret->version = 0;
ret->v.v0.dlhandle = NULL;
/* consider that struct isn't allocated by the library,
* `need_cleanup' flag might be set in lcb_create() */
ret->v.v0.need_cleanup = 0;
ret->v.v0.recv = lcb_io_recv;
ret->v.v0.send = lcb_io_send;
ret->v.v0.recvv = lcb_io_recvv;
Expand Down
3 changes: 3 additions & 0 deletions plugins/io/libevent/plugin-libevent.c
Expand Up @@ -342,6 +342,9 @@ lcb_error_t lcb_create_libevent_io_opts(lcb_io_opt_t *io, struct event_base *bas
/* setup io iops! */
ret->version = 0;
ret->v.v0.dlhandle = NULL;
/* consider that struct isn't allocated by the library,
* `need_cleanup' flag might be set in lcb_create() */
ret->v.v0.need_cleanup = 0;
ret->v.v0.recv = lcb_io_recv;
ret->v.v0.send = lcb_io_send;
ret->v.v0.recvv = lcb_io_recvv;
Expand Down
17 changes: 3 additions & 14 deletions src/instance.c
Expand Up @@ -225,6 +225,7 @@ lcb_error_t lcb_create(lcb_t *instance,
return err;
}
io = ops;
io->v.v0.need_cleanup = 1;
}

if (host == NULL) {
Expand Down Expand Up @@ -351,21 +352,9 @@ void lcb_destroy(lcb_t instance)
hashset_destroy(instance->http_requests);
free_backup_nodes(instance);
free(instance->servers);

if (instance->io) {
#ifndef _WIN32
void *dlhandle = instance->io->v.v0.dlhandle;
#endif
if (instance->io->v.v0.destructor) {
instance->io->v.v0.destructor(instance->io);
}
#ifndef _WIN32
if (dlhandle) {
dlclose(dlhandle);
}
#endif
if (instance->io->v.v0.need_cleanup) {
lcb_destroy_io_ops(instance->io);
}

free(instance->vbucket_stream.input.data);
free(instance->vbucket_stream.chunk.data);
free(instance->vbucket_stream.header);
Expand Down
25 changes: 25 additions & 0 deletions src/iofactory.c
Expand Up @@ -49,6 +49,15 @@ lcb_error_t lcb_create_io_ops(lcb_io_opt_t *io,

return LCB_SUCCESS;
}

LIBCOUCHBASE_API
lcb_error_t lcb_destroy_io_ops(lcb_io_opt_t io)
{
if (io && io->v.v0.destructor) {
io->v.v0.destructor(io);
}
return LCB_SUCCESS;
}
#else

typedef lcb_io_opt_t (*create_func)(struct event_base *base);
Expand Down Expand Up @@ -130,6 +139,22 @@ static void override_from_env(struct lcb_create_io_ops_st *options)

#undef USE_PLUGIN

LIBCOUCHBASE_API
lcb_error_t lcb_destroy_io_ops(lcb_io_opt_t io)
{
if (io) {
void *dlhandle = io->v.v0.dlhandle;
if (io->v.v0.destructor) {
io->v.v0.destructor(io);
}
if (dlhandle) {
dlclose(dlhandle);
}
}

return LCB_SUCCESS;
}

LIBCOUCHBASE_API
lcb_error_t lcb_create_io_ops(lcb_io_opt_t *io,
const struct lcb_create_io_ops_st *io_opts)
Expand Down

0 comments on commit a1b17df

Please sign in to comment.