Commit 2b985d07 authored by tsmith@ramayana.hindu.god's avatar tsmith@ramayana.hindu.god
Browse files

Applied InnoDB snapshot innodb-5.0-ss2095

Fixes the following bugs:

- Bug #29560: InnoDB >= 5.0.30 hangs on adaptive hash rw-lock 'waiting for an X-lock'

  Fixed a race condition in the rw_lock where an os_event_reset()
  can overwrite an earlier os_event_set() triggering an indefinite
  wait.
  NOTE: This fix for windows is different from that for other platforms.
  NOTE2: This bug is introduced in the scalability fix to the
  sync0arr which was applied to 5.0 only. Therefore, it need not be
  applied to the 5.1 tree. If we decide to port the scalability fix
  to 5.1 then this fix should be ported as well.

- Bug #32125: Database crash due to ha_innodb.cc:3896: ulint convert_search_mode_to_innobase

  When unknown find_flag is encountered in convert_search_mode_to_innobase()
  do not call assert(0); instead queue a MySQL error using my_error() and
  return the error code PAGE_CUR_UNSUPP. Change the functions that call
  convert_search_mode_to_innobase() to handle that error code by "canceling"
  execution and returning appropriate error code further upstream.
parent cb6885c1
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -57,6 +57,18 @@ Created 5/24/1996 Heikki Tuuri
					buffer pool (for big transactions,
					InnoDB stores the lock structs in the
					buffer pool) */
#define DB_FOREIGN_DUPLICATE_KEY 46	/* foreign key constraints
					activated by the operation would
					lead to a duplicate key in some
					table */
#define DB_TOO_MANY_CONCURRENT_TRXS 47	/* when InnoDB runs out of the
					preconfigured undo slots, this can
					only happen when there are too many
					concurrent transactions */
#define DB_UNSUPPORTED		48	/* when InnoDB sees any artefact or
					a feature that it can't recoginize or
					work with e.g., FT indexes created by
					a later version of the engine. */

/* The following are partial failure codes */
#define DB_FAIL 		1000
+32 −6
Original line number Diff line number Diff line
@@ -112,9 +112,13 @@ os_event_set(
	os_event_t	event);	/* in: event to set */
/**************************************************************
Resets an event semaphore to the nonsignaled state. Waiting threads will
stop to wait for the event. */
stop to wait for the event.
The return value should be passed to os_even_wait_low() if it is desired
that this thread should not wait in case of an intervening call to
os_event_set() between this os_event_reset() and the
os_event_wait_low() call. See comments for os_event_wait_low(). */

void
ib_longlong
os_event_reset(
/*===========*/
	os_event_t	event);	/* in: event to reset */
@@ -125,16 +129,38 @@ void
os_event_free(
/*==========*/
	os_event_t	event);	/* in: event to free */

/**************************************************************
Waits for an event object until it is in the signaled state. If
srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS this also exits the
waiting thread when the event becomes signaled (or immediately if the
event is already in the signaled state). */
event is already in the signaled state).

Typically, if the event has been signalled after the os_event_reset()
we'll return immediately because event->is_set == TRUE.
There are, however, situations (e.g.: sync_array code) where we may
lose this information. For example:

thread A calls os_event_reset()
thread B calls os_event_set()   [event->is_set == TRUE]
thread C calls os_event_reset() [event->is_set == FALSE]
thread A calls os_event_wait()  [infinite wait!]
thread C calls os_event_wait()  [infinite wait!]

Where such a scenario is possible, to avoid infinite wait, the
value returned by os_event_reset() should be passed in as
reset_sig_count. */

#define os_event_wait(event) os_event_wait_low((event), 0)

void
os_event_wait(
/*==========*/
	os_event_t	event);	/* in: event to wait */
os_event_wait_low(
/*==============*/
	os_event_t	event,		/* in: event to wait */
	ib_longlong	reset_sig_count);/* in: zero or the value
					returned by previous call of
					os_event_reset(). */

/**************************************************************
Waits for an event object until it is in the signaled state or
a timeout is exceeded. In Unix the timeout is always infinite. */
+1 −0
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ Created 10/4/1994 Heikki Tuuri

/* Page cursor search modes; the values must be in this order! */

#define	PAGE_CUR_UNSUPP	0
#define	PAGE_CUR_G	1
#define	PAGE_CUR_GE	2
#define	PAGE_CUR_L	3
+11 −0
Original line number Diff line number Diff line
@@ -418,6 +418,17 @@ field. Then no new readers are allowed in. */

struct rw_lock_struct {
	os_event_t	event;	/* Used by sync0arr.c for thread queueing */

#ifdef __WIN__
	os_event_t	wait_ex_event;	/* This windows specific event is
				used by the thread which has set the
				lock state to RW_LOCK_WAIT_EX. The
				rw_lock design guarantees that this
				thread will be the next one to proceed
				once the current the event gets
				signalled. See LEMMA 2 in sync0sync.c */
#endif

	ulint	reader_count;	/* Number of readers who have locked this
				lock in the shared mode */
	ulint	writer; 	/* This field is set to RW_LOCK_EX if there
+6 −0
Original line number Diff line number Diff line
@@ -382,6 +382,9 @@ rw_lock_s_unlock_func(
	mutex_exit(mutex);

	if (UNIV_UNLIKELY(sg)) {
#ifdef __WIN__
		os_event_set(lock->wait_ex_event);
#endif
		os_event_set(lock->event);
		sync_array_object_signalled(sync_primary_wait_array);
	}
@@ -463,6 +466,9 @@ rw_lock_x_unlock_func(
	mutex_exit(&(lock->mutex));

	if (UNIV_UNLIKELY(sg)) {
#ifdef __WIN__
		os_event_set(lock->wait_ex_event);
#endif
		os_event_set(lock->event);
		sync_array_object_signalled(sync_primary_wait_array);
	}
Loading