Changeset: 4469ecb45f6d for MonetDB URL: https://dev.monetdb.org/hg/MonetDB/rev/4469ecb45f6d Branch: default Log Message:
Merge with Sep2022 branch. diffs (277 lines): diff --git a/common/utils/mutils.c b/common/utils/mutils.c --- a/common/utils/mutils.c +++ b/common/utils/mutils.c @@ -468,9 +468,17 @@ MT_lockf(const char *filename, int mode) wchar_t *wfilename; int fildes; } *lockedfiles; + static CRITICAL_SECTION cs; + static bool inited = false; struct lockedfiles **fpp, *fp; wchar_t *wfilename; + if (!inited) { + /* here we're still running single threaded */ + InitializeCriticalSection(&cs); + inited = true; /* only time this is changed */ + } + if ((wfilename = utf8towchar(filename)) == NULL) return -2; ov = (OVERLAPPED) {0}; @@ -483,19 +491,21 @@ MT_lockf(const char *filename, int mode) #endif if (mode == F_ULOCK) { + EnterCriticalSection(&cs); for (fpp = &lockedfiles; (fp = *fpp) != NULL; fpp = &fp->next) { if (wcscmp(fp->wfilename, wfilename) == 0) { + *fpp = fp->next; + LeaveCriticalSection(&cs); free(fp->wfilename); fd = fp->fildes; fh = (HANDLE) _get_osfhandle(fd); - fp = *fpp; - *fpp = fp->next; free(fp); ret = UnlockFileEx(fh, 0, 1, 0, &ov); free(wfilename); return ret ? 0 : -1; } } + LeaveCriticalSection(&cs); /* didn't find the locked file, try opening the file * directly */ fh = CreateFileW(wfilename, @@ -542,8 +552,10 @@ MT_lockf(const char *filename, int mode) if ((fp = malloc(sizeof(*fp))) != NULL) { fp->wfilename = wfilename; fp->fildes = fd; + EnterCriticalSection(&cs); fp->next = lockedfiles; lockedfiles = fp; + LeaveCriticalSection(&cs); } else { free(wfilename); } @@ -752,6 +764,8 @@ lockf(int fd, int cmd, off_t len) } #endif +#include <pthread.h> + #ifndef O_TEXT #define O_TEXT 0 #endif @@ -763,19 +777,57 @@ lockf(int fd, int cmd, off_t len) int MT_lockf(const char *filename, int mode) { - int fd = open(filename, O_CREAT | O_RDWR | O_TEXT | O_CLOEXEC, MONETDB_MODE); + static struct lockfile { + char *filename; + int fd; + struct lockfile *next; + } *lockfiles = NULL; + static pthread_mutex_t cs = PTHREAD_MUTEX_INITIALIZER; + struct lockfile *fp; + int fd; + off_t seek; + + if (mode == F_ULOCK) { + pthread_mutex_lock(&cs); + for (struct lockfile **fpp = &lockfiles; (fp = *fpp) != NULL; fpp = &fp->next) { + if (strcmp(fp->filename, filename) == 0) { + *fpp = fp->next; + pthread_mutex_unlock(&cs); + free(fp->filename); + fd = fp->fd; + free(fp); + seek = lseek(fd, 4, SEEK_SET); + int ret = lockf(fd, mode, 1); + (void) lseek(fd, seek, SEEK_SET); /* move seek pointer back */ + /* do not close fd, it is closed by caller */ + return ret; /* 0 if unlock successful, -1 if not */ + } + } + } + fd = open(filename, O_CREAT | O_RDWR | O_TEXT | O_CLOEXEC, MONETDB_MODE); if (fd < 0) return -2; - if (lseek(fd, 4, SEEK_SET) >= 0 && + if ((seek = lseek(fd, 4, SEEK_SET)) >= 0 && lockf(fd, mode, 1) == 0) { if (mode == F_ULOCK || mode == F_TEST) { close(fd); return 0; } + if ((fp = malloc(sizeof(*fp))) != NULL) { + if ((fp->filename = strdup(filename)) != NULL) { + fp->fd = fd; + pthread_mutex_lock(&cs); + fp->next = lockfiles; + lockfiles = fp; + pthread_mutex_unlock(&cs); + } else { + free(fp); + } + } /* do not close else we lose the lock we want */ - (void) lseek(fd, 0, SEEK_SET); /* move seek pointer back */ + (void) lseek(fd, seek, SEEK_SET); /* move seek pointer back */ return fd; } close(fd); diff --git a/sql/test/concurrent/Tests/read-segment-after-free.timeout b/sql/test/concurrent/Tests/read-segment-after-free.timeout new file mode 100644 --- /dev/null +++ b/sql/test/concurrent/Tests/read-segment-after-free.timeout @@ -0,0 +1,1 @@ +2 diff --git a/sql/test/copy/Tests/nonutf8.py b/sql/test/copy/Tests/nonutf8.SQL.py rename from sql/test/copy/Tests/nonutf8.py rename to sql/test/copy/Tests/nonutf8.SQL.py --- a/sql/test/copy/Tests/nonutf8.py +++ b/sql/test/copy/Tests/nonutf8.SQL.py @@ -19,9 +19,12 @@ with process.client('sql', text=False, s retcode = c.returncode if retcode == 0: - sys.stderr.write("Expected nonzero return code") + print(f"Expected nonzero return code, received {retcode}", + file=sys.stderr) if not err or b'invalid start of UTF-8 sequence' not in err: - sys.stderr.write("Expected stderr to contain 'invalid start of UTF-8 sequence'") + print("Expected stderr to contain 'invalid start of UTF-8 sequence'", + file=sys.stderr) + print(f"Received: {err}", file=sys.stderr) # input is a byte string because it contains broken utf-8 INPUT2 = b""" @@ -34,9 +37,12 @@ with process.client('sql', text=False, s retcode = c.returncode if retcode == 0: - sys.stderr.write("Expected nonzero return code") + print(f"Expected nonzero return code, received {retcode}", + file=sys.stderr) if not err or b'input not properly encoded UTF-8' not in err: - sys.stderr.write("Expected stderr to contain 'input not properly encoded UTF-8'") + print("Expected stderr to contain 'input not properly encoded UTF-8'", + file=sys.stderr) + print(f"Received: {err}", file=sys.stderr) with SQLTestCase() as tc: tc.connect(username="monetdb", password="monetdb") diff --git a/testing/Mtest.py.in b/testing/Mtest.py.in --- a/testing/Mtest.py.in +++ b/testing/Mtest.py.in @@ -1355,7 +1355,7 @@ def PerformDir(env, testdir, testlist, t else: vaultopt = [] if not oneserver: - pSrvr = ServerClass(splitcommand(env['exe']['mserver5'][1]) + ['--dbpath=%s' % LogDBdir] + vaultopt + mserver5_opts, open(os.devnull, 'w'), open(os.devnull, 'w'), par['TIMEOUT'], os.path.join(LogDBdir, '.started')) + pSrvr = ServerClass(splitcommand(env['exe']['mserver5'][1] +['--dbpath=%s' % LogDBdir] + vaultopt + mserver5_opts), open(os.devnull, 'w'), open(os.devnull, 'w'), par['TIMEOUT'], os.path.join(LogDBdir, '.started'), dbg=env.get('DBG')) pSrvr.LaunchIt() pSrvr.terminate() if not os.path.exists(TSTTRGDIR): @@ -1401,7 +1401,8 @@ def PerformDir(env, testdir, testlist, t openutf8(os.path.join(TSTTRGDIR, 'SingleServer.err'), 'a'), 0, pollfile, - inmem=inmem) + inmem=inmem, + dbg=env.get('DBG')) os.chdir(TSTTRGDIR) pSrvr.LaunchIt() if pSrvr.port is None: @@ -2574,7 +2575,7 @@ def killProc(proc, outfile = None, cmd = killchildren(proc.pid) class ServerClass: - def __init__(self, cmd, TestOut, TestErr, TimeOut, pollfile, inmem=False): + def __init__(self, cmd, TestOut, TestErr, TimeOut, pollfile, inmem=False, dbg=None): self.proc = None self.timer = None self.outfile = TestOut @@ -2585,6 +2586,7 @@ class ServerClass: self.timeout = TimeOut self.pollfile = pollfile self.inmem = inmem + self.dbg = dbg def poll(self): return self.proc.poll() @@ -2614,25 +2616,31 @@ class ServerClass: if procdebug: print('LaunchIt: starting process "%s" (inpipe)\n' % '" "'.join(self.cmd)) setpgrp = True - outfile = self.outfile + stdin = open(os.devnull) + stdout = self.outfile + stderr = self.errfile + cmd = self.cmd if self.inmem: - outfile = process.PIPE + stdout = process.PIPE elif self.pollfile: try: os.unlink(self.pollfile) except OSError: pass + if self.dbg: + stdin = stdout = stderr = None + cmd = splitcommand(self.dbg) + self.cmd else: - outfile = process.PIPE + stdout = process.PIPE if os.name == "nt": - proc = process.Popen(self.cmd, stdin=open(os.devnull), stdout=outfile, - stderr=self.errfile, text=True, + proc = process.Popen(cmd, stdin=stdin, stdout=stdout, + stderr=stderr, text=True, creationflags=process.CREATE_NEW_PROCESS_GROUP) else: - proc = process.Popen(self.cmd, stdin=open(os.devnull), stdout=outfile, - stderr=self.errfile, text=True) + proc = process.Popen(cmd, stdin=stdin, stdout=stdout, + stderr=stderr, text=True) # maybe buffer output as it comes to avoid deadlock - if outfile == process.PIPE: + if stdout == process.PIPE: proc.stdout = process._BufferedPipe(proc.stdout) if self.errfile == process.PIPE: proc.stderr = process._BufferedPipe(proc.stderr) @@ -2831,7 +2839,7 @@ def DoIt(env, SERVER, CALL, TST, EXT, Te if os.path.isfile(TST + '.options5'): Srvr.extend(openutf8(TST + '.options5').read().split()) Srvr.extend(mserver5_opts) - pSrvr = ServerClass(Srvr, SrvrOut, SrvrErr, TIMEOUT, os.path.join(dbpath, '.started')) + pSrvr = ServerClass(Srvr, SrvrOut, SrvrErr, TIMEOUT, os.path.join(dbpath, '.started'), dbg=env.get('DBG')) pSrvr.LaunchIt() if pSrvr.port is None: print('\nFailed to start server.\n') @@ -3658,10 +3666,6 @@ def main(argv) : env['setMONETDB_MOD_PATH'] = eval(dft['setMONETDB_MOD_PATH']) else: env['setMONETDB_MOD_PATH'] = '' - if 'DBG' in env: - env['setDBG'] = env['DBG'] - else: - env['setDBG'] = '' #TODO: ## in case of inconsistencies, try to fallback to "save" settings @@ -3847,8 +3851,8 @@ def main(argv) : SOCK = "" exe = {} - exe['mserver5'] = CheckExec('mserver5') , '%s mserver5 --debug=%s --set gdk_nr_threads=%s %s --set mapi_listenaddr=all --set mapi_port=0 %s %s' % \ - (env['setDBG'], env['GDK_DEBUG'], env['GDK_NR_THREADS'], env['setMONETDB_MOD_PATH'], SOCK, not nomito and '--forcemito' or '') + exe['mserver5'] = CheckExec('mserver5') , 'mserver5 --debug=%s --set gdk_nr_threads=%s %s --set mapi_listenaddr=all --set mapi_port=0 %s %s' % \ + (env['GDK_DEBUG'], env['GDK_NR_THREADS'], env['setMONETDB_MOD_PATH'], SOCK, not nomito and '--forcemito' or '') exe['ruby_client'] = CheckExec(env['RUBYCLIENT'].split(None, 1)[0]) , '%s %s' % (env['RUBYCLIENT'], '${PORT}') exe['MAL_Client'] = CheckExec(env['MALCLIENT'].split(None, 1)[0]) , '%s --host=%s --port=%s' % (env['MALCLIENT'], HOST, '${PORT}') exe['SQL_Client'] = CheckExec(env['SQLCLIENT'].split(None, 1)[0]) , '%s -i -e --host=%s --port=%s' % (env['SQLCLIENT'], HOST, '${PORT}') _______________________________________________ checkin-list mailing list -- checkin-list@monetdb.org To unsubscribe send an email to checkin-list-le...@monetdb.org