static void *nogvl_close(void *ptr) { mysql_client_wrapper *wrapper; wrapper = ptr; if (wrapper->connected) { wrapper->active_thread = Qnil; wrapper->connected = 0; #ifndef _WIN32 /* Invalidate the socket before calling mysql_close(). This prevents * mysql_close() from sending a mysql-QUIT or from calling shutdown() on * the socket. The difference is that invalidate_fd will drop this * process's reference to the socket only, while a QUIT or shutdown() * would render the underlying connection unusable, interrupting other * processes which share this object across a fork(). */ if (invalidate_fd(wrapper->client->net.fd) == Qfalse) { fprintf(stderr, "[WARN] mysql2 failed to invalidate FD safely, leaking some memory\n"); close(wrapper->client->net.fd); return NULL; } #endif mysql_close(wrapper->client); /* only used to free memory at this point */ } return NULL; }
void decr_mysql2_client(mysql_client_wrapper *wrapper) { wrapper->refcount--; if (wrapper->refcount == 0) { #ifndef _WIN32 if (wrapper->connected && !wrapper->automatic_close) { /* The client is being garbage collected while connected. Prevent * mysql_close() from sending a mysql-QUIT or from calling shutdown() on * the socket by invalidating it. invalidate_fd() will drop this * process's reference to the socket only, while a QUIT or shutdown() * would render the underlying connection unusable, interrupting other * processes which share this object across a fork(). */ if (invalidate_fd(wrapper->client->net.fd) == Qfalse) { fprintf(stderr, "[WARN] mysql2 failed to invalidate FD safely\n"); close(wrapper->client->net.fd); } } #endif nogvl_close(wrapper); xfree(wrapper); } }
int comm_snd(struct cnid_dbd_rply *rply) { #ifdef USE_WRITEV struct iovec iov[2]; size_t towrite; #endif if (!rply->namelen) { if (write(cur_fd, rply, sizeof(struct cnid_dbd_rply)) != sizeof(struct cnid_dbd_rply)) { LOG(log_error, logtype_cnid, "error writing message header: %s", strerror(errno)); invalidate_fd(cur_fd); return 0; } return 1; } #ifdef USE_WRITEV iov[0].iov_base = rply; iov[0].iov_len = sizeof(struct cnid_dbd_rply); iov[1].iov_base = rply->name; iov[1].iov_len = rply->namelen; towrite = sizeof(struct cnid_dbd_rply) +rply->namelen; if (writev(cur_fd, iov, 2) != towrite) { LOG(log_error, logtype_cnid, "error writing message : %s", strerror(errno)); invalidate_fd(cur_fd); return 0; } #else if (write(cur_fd, rply, sizeof(struct cnid_dbd_rply)) != sizeof(struct cnid_dbd_rply)) { LOG(log_error, logtype_cnid, "error writing message header: %s", strerror(errno)); invalidate_fd(cur_fd); return 0; } if (write(cur_fd, rply->name, rply->namelen) != rply->namelen) { LOG(log_error, logtype_cnid, "error writing message name: %s", strerror(errno)); invalidate_fd(cur_fd); return 0; } #endif return 1; }
/* ------------ */ int comm_rcv(struct cnid_dbd_rqst *rqst, time_t timeout, const sigset_t *sigmask, time_t *now) { char *nametmp; int b; if ((cur_fd = check_fd(timeout, sigmask, now)) < 0) return -1; if (!cur_fd) return 0; LOG(log_maxdebug, logtype_cnid, "comm_rcv: got data on fd %u", cur_fd); if (setnonblock(cur_fd, 1) != 0) { LOG(log_error, logtype_cnid, "comm_rcv: setnonblock: %s", strerror(errno)); return -1; } nametmp = (char *)rqst->name; if ((b = readt(cur_fd, rqst, sizeof(struct cnid_dbd_rqst), 1, CNID_DBD_TIMEOUT)) != sizeof(struct cnid_dbd_rqst)) { if (b) LOG(log_error, logtype_cnid, "error reading message header: %s", strerror(errno)); invalidate_fd(cur_fd); rqst->name = nametmp; return 0; } rqst->name = nametmp; if (rqst->namelen && readt(cur_fd, (char *)rqst->name, rqst->namelen, 1, CNID_DBD_TIMEOUT) != rqst->namelen) { LOG(log_error, logtype_cnid, "error reading message name: %s", strerror(errno)); invalidate_fd(cur_fd); return 0; } /* We set this to make life easier for logging. None of the other stuff needs zero terminated strings. */ ((char *)(rqst->name))[rqst->namelen] = '\0'; LOG(log_maxdebug, logtype_cnid, "comm_rcv: got %u bytes", b + rqst->namelen); return 1; }
int my_win_close(File fd) { DBUG_ENTER("my_win_close"); if(CloseHandle(my_get_osfhandle(fd))) { invalidate_fd(fd); DBUG_RETURN(0); } my_osmaperr(GetLastError()); DBUG_RETURN(-1); }
int my_win_fclose(FILE *file) { File fd; DBUG_ENTER("my_win_close"); fd= my_fileno(file); if(fd < 0) DBUG_RETURN(-1); if(fclose(file) < 0) DBUG_RETURN(-1); invalidate_fd(fd); DBUG_RETURN(0); }
static VALUE disconnect_and_raise(VALUE self, VALUE error) { GET_CLIENT(self); MARK_CONN_INACTIVE(self); wrapper->connected = 0; /* Invalidate the MySQL socket to prevent further communication. * The GC will come along later and call mysql_close to free it. */ if (invalidate_fd(wrapper->client->net.fd) == Qfalse) { fprintf(stderr, "[WARN] mysql2 failed to invalidate FD safely, closing unsafely\n"); close(wrapper->client->net.fd); } rb_exc_raise(error); }
static VALUE disconnect_and_mark_inactive(VALUE self) { GET_CLIENT(self); /* Check if execution terminated while result was still being read. */ if (!NIL_P(wrapper->active_thread)) { if (CONNECTED(wrapper)) { /* Invalidate the MySQL socket to prevent further communication. */ #ifndef _WIN32 if (invalidate_fd(wrapper->client->net.fd) == Qfalse) { rb_warn("mysql2 failed to invalidate FD safely, closing unsafely\n"); close(wrapper->client->net.fd); } #else close(wrapper->client->net.fd); #endif wrapper->client->net.fd = -1; } /* Skip mysql client check performed before command execution. */ wrapper->client->status = MYSQL_STATUS_READY; wrapper->active_thread = Qnil; } return Qnil; }