Changeset: e582a038df7a for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/e582a038df7a
Modified Files:
        gdk/gdk_bat.c
        gdk/gdk_batop.c
        gdk/gdk_bbp.c
        gdk/gdk_hash.c
        gdk/gdk_private.h
        gdk/gdk_storage.c
Branch: default
Log Message:

Merge with Sep2022 branch.


diffs (truncated from 302 to 300 lines):

diff --git a/gdk/ChangeLog.Sep2022 b/gdk/ChangeLog.Sep2022
--- a/gdk/ChangeLog.Sep2022
+++ b/gdk/ChangeLog.Sep2022
@@ -1,6 +1,12 @@
 # ChangeLog file for GDK
 # This file is updated with Maddlog
 
+* Wed Dec 14 2022 Sjoerd Mullender <sjo...@acm.org>
+- Fixed a race condition where a hash could have been created on a
+  bat using the old bat count while in another thread the bat count
+  got updated.  This would make the hash be based on too small a size,
+  causing failures later on.
+
 * Thu Dec  8 2022 Sjoerd Mullender <sjo...@acm.org>
 - When extending a bat failed, the capacity had been updated already and
   was therefore too large.  This could then later cause a crash.  This has
diff --git a/gdk/gdk_bat.c b/gdk/gdk_bat.c
--- a/gdk/gdk_bat.c
+++ b/gdk/gdk_bat.c
@@ -1175,6 +1175,7 @@ BUNappendmulti(BAT *b, const void *value
        }
        BATiter bi = bat_iterator_nolock(b);
        MT_lock_unset(&b->theaplock);
+       MT_rwlock_wrlock(&b->thashlock);
        if (values && b->ttype) {
                int (*atomcmp) (const void *, const void *) = 
ATOMcompare(b->ttype);
                const void *atomnil = ATOMnilptr(b->ttype);
@@ -1189,6 +1190,7 @@ BUNappendmulti(BAT *b, const void *value
                                t = ((void **) values)[i];
                                gdk_return rc = tfastins_nocheckVAR(b, p, t);
                                if (rc != GDK_SUCCEED) {
+                                       MT_rwlock_wrunlock(&b->thashlock);
                                        return rc;
                                }
                                if (vbase != b->tvheap->base) {
@@ -1229,7 +1231,6 @@ BUNappendmulti(BAT *b, const void *value
                                }
                                p++;
                        }
-                       MT_rwlock_wrlock(&b->thashlock);
                        if (b->thash) {
                                p -= count;
                                for (BUN i = 0; i < count; i++) {
@@ -1239,7 +1240,6 @@ BUNappendmulti(BAT *b, const void *value
                                }
                                nunique = b->thash ? b->thash->nunique : 0;
                        }
-                       MT_rwlock_wrunlock(&b->thashlock);
                } else if (ATOMstorage(b->ttype) == TYPE_msk) {
                        bi.minpos = bi.maxpos = BUN_NONE;
                        minvalp = maxvalp = NULL;
@@ -1253,7 +1253,6 @@ BUNappendmulti(BAT *b, const void *value
                                minvalp = BUNtloc(bi, bi.minpos);
                        if (bi.maxpos != BUN_NONE)
                                maxvalp = BUNtloc(bi, bi.maxpos);
-                       MT_rwlock_wrlock(&b->thashlock);
                        for (BUN i = 0; i < count; i++) {
                                t = (void *) ((char *) values + (i << 
b->tshift));
                                gdk_return rc = tfastins_nocheckFIX(b, p, t);
@@ -1284,14 +1283,12 @@ BUNappendmulti(BAT *b, const void *value
                                p++;
                        }
                        nunique = b->thash ? b->thash->nunique : 0;
-                       MT_rwlock_wrunlock(&b->thashlock);
                }
                MT_lock_set(&b->theaplock);
                b->tminpos = bi.minpos;
                b->tmaxpos = bi.maxpos;
                MT_lock_unset(&b->theaplock);
        } else {
-               MT_rwlock_wrlock(&b->thashlock);
                for (BUN i = 0; i < count; i++) {
                        gdk_return rc = tfastins_nocheck(b, p, t);
                        if (rc != GDK_SUCCEED) {
@@ -1304,13 +1301,13 @@ BUNappendmulti(BAT *b, const void *value
                        p++;
                }
                nunique = b->thash ? b->thash->nunique : 0;
-               MT_rwlock_wrunlock(&b->thashlock);
        }
        MT_lock_set(&b->theaplock);
        BATsetcount(b, p);
        if (nunique != 0)
                b->tunique_est = (double) nunique;
        MT_lock_unset(&b->theaplock);
+       MT_rwlock_wrunlock(&b->thashlock);
 
        IMPSdestroy(b); /* no support for inserts in imprints yet */
        OIDXdestroy(b);
@@ -1588,14 +1585,11 @@ BUNinplacemulti(BAT *b, const oid *posit
                        }
                        if (b->twidth < SIZEOF_VAR_T &&
                            (b->twidth <= 2 ? _d - GDK_VAROFFSET : _d) >= 
((size_t) 1 << (8 << b->tshift))) {
-                               /* doesn't fit in current heap, upgrade
-                                * it, can't keep hashlock while doing
-                                * so */
-                               MT_rwlock_wrunlock(&b->thashlock);
+                               /* doesn't fit in current heap, upgrade it */
                                if (GDKupgradevarheap(b, _d, 0, bi.count) != 
GDK_SUCCEED) {
+                                       MT_rwlock_wrunlock(&b->thashlock);
                                        return GDK_FAIL;
                                }
-                               MT_rwlock_wrlock(&b->thashlock);
                        }
                        /* reinitialize iterator after possible heap upgrade */
                        {
diff --git a/gdk/gdk_batop.c b/gdk/gdk_batop.c
--- a/gdk/gdk_batop.c
+++ b/gdk/gdk_batop.c
@@ -304,12 +304,12 @@ insert_string_bat(BAT *b, BATiter *ni, s
                }
        }
        TIMEOUT_CHECK(timeoffset, TIMEOUT_HANDLER(GDK_FAIL));
+       MT_rwlock_wrlock(&b->thashlock);
        MT_lock_set(&b->theaplock);
        BATsetcount(b, oldcnt + ci->ncand);
        assert(b->batCapacity >= b->batCount);
        MT_lock_unset(&b->theaplock);
        /* maintain hash */
-       MT_rwlock_wrlock(&b->thashlock);
        for (r = oldcnt, cnt = BATcount(b); b->thash && r < cnt; r++) {
                HASHappend_locked(b, r, b->tvheap->base + VarHeapVal(Tloc(b, 
0), r, b->twidth));
        }
@@ -382,11 +382,11 @@ append_varsized_bat(BAT *b, BATiter *ni,
                                *dst++ = src[canditer_next(ci) - hseq];
                        }
                }
+               MT_rwlock_wrlock(&b->thashlock);
                MT_lock_set(&b->theaplock);
                BATsetcount(b, BATcount(b) + ci->ncand);
                MT_lock_unset(&b->theaplock);
                /* maintain hash table */
-               MT_rwlock_wrlock(&b->thashlock);
                for (BUN i = BATcount(b) - ci->ncand;
                     b->thash && i < BATcount(b);
                     i++) {
@@ -477,12 +477,12 @@ append_varsized_bat(BAT *b, BATiter *ni,
                }
        }
        BUN nunique = b->thash ? b->thash->nunique : 0;
-       MT_rwlock_wrunlock(&b->thashlock);
        MT_lock_set(&b->theaplock);
        BATsetcount(b, r);
        if (nunique != 0)
                b->tunique_est = (double) nunique;
        MT_lock_unset(&b->theaplock);
+       MT_rwlock_wrunlock(&b->thashlock);
        return GDK_SUCCEED;
 }
 
@@ -904,12 +904,12 @@ BATappend2(BAT *b, BAT *n, BAT *s, bool 
                }
                BUN nunique;
                nunique = b->thash ? b->thash->nunique : 0;
-               MT_rwlock_wrunlock(&b->thashlock);
                MT_lock_set(&b->theaplock);
                BATsetcount(b, b->batCount + ci.ncand);
                if (nunique != 0)
                        b->tunique_est = (double) nunique;
                MT_lock_unset(&b->theaplock);
+               MT_rwlock_wrunlock(&b->thashlock);
        }
 
   doreturn:
@@ -1320,16 +1320,10 @@ BATappend_or_update(BAT *b, BAT *p, cons
                        }
                        if (b->twidth < SIZEOF_VAR_T &&
                            (b->twidth <= 2 ? d - GDK_VAROFFSET : d) >= 
((size_t) 1 << (8 << b->tshift))) {
-                               /* doesn't fit in current heap, upgrade
-                                * it, can't keep hashlock while doing
-                                * so */
-                               MT_rwlock_wrunlock(&b->thashlock);
-                               locked = false;
+                               /* doesn't fit in current heap, upgrade it */
                                if (GDKupgradevarheap(b, d, 0, MAX(updid, 
b->batCount)) != GDK_SUCCEED) {
                                        goto bailout;
                                }
-                               MT_rwlock_wrlock(&b->thashlock);
-                               locked = true;
                        }
                        /* in case ATOMreplaceVAR and/or
                         * GDKupgradevarheap replaces a heap, we need to
@@ -1373,6 +1367,7 @@ BATappend_or_update(BAT *b, BAT *p, cons
                b->tvheap->dirty = true;
                MT_lock_unset(&b->theaplock);
        } else if (ATOMstorage(b->ttype) == TYPE_msk) {
+               assert(b->thash == NULL);
                HASHdestroy(b); /* hash doesn't make sense for msk */
                for (BUN i = 0; i < ni.count; i++) {
                        oid updid;
diff --git a/gdk/gdk_bbp.c b/gdk/gdk_bbp.c
--- a/gdk/gdk_bbp.c
+++ b/gdk/gdk_bbp.c
@@ -3786,9 +3786,7 @@ BBPsync(int cnt, bat *restrict subcommit
                                        BBP_status_on(i, BBPSAVING);
                                        if (lock)
                                                MT_lock_unset(&GDKswapLock(i));
-                                       MT_rwlock_rdlock(&b->thashlock);
-                                       ret = BATsave_locked(b, &bi, size);
-                                       MT_rwlock_rdunlock(&b->thashlock);
+                                       ret = BATsave_iter(b, &bi, size);
                                        BBP_status_off(i, BBPSAVING);
                                }
                        } else {
diff --git a/gdk/gdk_hash.c b/gdk/gdk_hash.c
--- a/gdk/gdk_hash.c
+++ b/gdk/gdk_hash.c
@@ -609,6 +609,7 @@ BAThashsave_intern(BAT *b, bool dosync)
                /* only persist if parent BAT hasn't changed in the
                 * mean time */
                if (!b->theap->dirty &&
+                   ((size_t *) h->heapbckt.base)[1] == BATcount(b) &&
                    ((size_t *) h->heapbckt.base)[4] == BATcount(b) &&
                    HEAPsave(&h->heaplink, h->heaplink.filename, NULL, dosync, 
h->heaplink.free, NULL) == GDK_SUCCEED &&
                    HEAPsave(&h->heapbckt, h->heapbckt.filename, NULL, dosync, 
h->heapbckt.free, NULL) == GDK_SUCCEED) {
diff --git a/gdk/gdk_private.h b/gdk/gdk_private.h
--- a/gdk/gdk_private.h
+++ b/gdk/gdk_private.h
@@ -86,7 +86,7 @@ void BATrmprop(BAT *b, enum prop_t idx)
        __attribute__((__visibility__("hidden")));
 void BATrmprop_nolock(BAT *b, enum prop_t idx)
        __attribute__((__visibility__("hidden")));
-gdk_return BATsave_locked(BAT *bd, BATiter *bi, BUN size)
+gdk_return BATsave_iter(BAT *bd, BATiter *bi, BUN size)
        __attribute__((__visibility__("hidden")));
 void BATsetdims(BAT *b, uint16_t width)
        __attribute__((__visibility__("hidden")));
diff --git a/gdk/gdk_storage.c b/gdk/gdk_storage.c
--- a/gdk/gdk_storage.c
+++ b/gdk/gdk_storage.c
@@ -661,23 +661,31 @@ DESCload(int i)
 }
 
 gdk_return
-BATsave_locked(BAT *b, BATiter *bi, BUN size)
+BATsave_iter(BAT *b, BATiter *bi, BUN size)
 {
        gdk_return err = GDK_SUCCEED;
        const char *nme;
        bool dosync;
+       bool locked = false;
 
        BATcheck(b, GDK_FAIL);
 
+       if (MT_rwlock_rdtry(&b->thashlock))
+               locked = true;
+
        dosync = (BBP_status(b->batCacheid) & BBPPERSISTENT) != 0;
        assert(!GDKinmemory(bi->h->farmid));
        /* views cannot be saved, but make an exception for
         * force-remapped views */
        if (isVIEW(b)) {
+               if (locked)
+                       MT_rwlock_rdunlock(&b->thashlock);
                GDKerror("%s is a view on %s; cannot be saved\n", BATgetId(b), 
BBP_logical(VIEWtparent(b)));
                return GDK_FAIL;
        }
        if (!BATdirtybi(*bi)) {
+               if (locked)
+                       MT_rwlock_rdunlock(&b->thashlock);
                return GDK_SUCCEED;
        }
 
@@ -760,9 +768,11 @@ BATsave_locked(BAT *b, BATiter *bi, BUN 
                        b->batCopiedtodisk = true;
                }
                MT_lock_unset(&b->theaplock);
-               if (b->thash && b->thash != (Hash *) 1)
+               if (locked &&  b->thash && b->thash != (Hash *) 1)
                        BAThashsave(b, dosync);
        }
+       if (locked)
+               MT_rwlock_rdunlock(&b->thashlock);
        return err;
 }
 
@@ -772,9 +782,7 @@ BATsave(BAT *b)
        gdk_return rc;
 
        BATiter bi = bat_iterator(b);
-       MT_rwlock_rdlock(&b->thashlock);
-       rc = BATsave_locked(b, &bi, bi.count);
-       MT_rwlock_rdunlock(&b->thashlock);
+       rc = BATsave_iter(b, &bi, bi.count);
        bat_iterator_end(&bi);
        return rc;
 }
diff --git a/sql/ChangeLog.Sep2022 b/sql/ChangeLog.Sep2022
--- a/sql/ChangeLog.Sep2022
+++ b/sql/ChangeLog.Sep2022
@@ -1,6 +1,11 @@
 # ChangeLog file for sql
 # This file is updated with Maddlog
 
+* Wed Dec 14 2022 Sjoerd Mullender <sjo...@acm.org>
+- Fixed cleanup after a failed allocation where the data being cleaned
+  up was unitialized but still used as pointers to memory that also had
+  to be freed.
+
 * Wed Dec  7 2022 Sjoerd Mullender <sjo...@acm.org>
_______________________________________________
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org

Reply via email to