This topic has gone quiet and I've not seen any of the patches appear in CVS; its been over a year!
I've just applied the patches and some tweaks to the 1.4.0 base and they seem to work ok. I also tweaked some errno handling in the patch and fixed a bug whereby a failed fstat would return no result to a lock attempt. The #ifdef SunOS probably should be replaced with #ifdef HAS_BROKEN_FLOCK in most cases, as there are probably other SVR4 systems out there that could benefit from this multi-threaded locking support. I enclose my patch relative to the 1.4.0 base (with more context than the original patch as patching from that gave some errors). I also enclose a fix for Solaris and any other SVR4 based system to support logfile rotation using SIGHUP... the original code would die on the 2nd SIGHUP due to the signal handler not being reinstated. Using sigaction instead on such systems. (#ifdef SA_RESTART) I also tweaked configure for Solaris 9 x86, as it only supported recognition of sparc with gcc. Ian D
diff -rc mbuni-1.4.0_orig/configure mbuni-1.4.0/configure *** mbuni-1.4.0_orig/configure Sat Jul 12 04:59:39 2008 --- mbuni-1.4.0/configure Tue Dec 8 05:40:07 2009 *************** *** 21887,21893 **** EXE_EXT="" LIB_EXT="a" case "$host" in ! *-sun-solaris* | *SunOS*) CFLAGS="$CFLAGS -DSunOS=1 -D_POSIX_PTHREAD_SEMANTICS" ;; *-cygwin*) --- 21887,21893 ---- EXE_EXT="" LIB_EXT="a" case "$host" in ! *-sun-solaris* | *-pc-solaris* | *SunOS*) CFLAGS="$CFLAGS -DSunOS=1 -D_POSIX_PTHREAD_SEMANTICS" ;; *-cygwin*) diff -rc mbuni-1.4.0_orig/mmlib/mms_mmbox.c mbuni-1.4.0/mmlib/mms_mmbox.c *** mbuni-1.4.0_orig/mmlib/mms_mmbox.c Thu Jul 10 07:54:44 2008 --- mbuni-1.4.0/mmlib/mms_mmbox.c Tue Dec 8 03:08:48 2009 *************** *** 178,184 **** if (fd >= 0 && mm_lockfile(fd,ctmp,1) != 0) { unlink(ctmp); ! close(fd); fd = -1; } octstr_destroy(tmp); --- 178,184 ---- if (fd >= 0 && mm_lockfile(fd,ctmp,1) != 0) { unlink(ctmp); ! unlock_and_close(fd); fd = -1; } octstr_destroy(tmp); *************** *** 202,208 **** fbuf, strerror(errno)); break; } else if (mm_lockfile(fd, fbuf, shouldblock) != 0) { ! close(fd); fd = -1; } while (i++ < MAXTRIES && fd < 0); --- 202,208 ---- fbuf, strerror(errno)); break; } else if (mm_lockfile(fd, fbuf, shouldblock) != 0) { ! unlock_and_close(fd); fd = -1; } while (i++ < MAXTRIES && fd < 0); *************** *** 272,278 **** error(0, "mmbox.update_index: Failed lock temp file %s: error = %s\n", fbuf, strerror(errno)); ! close(tempfd); tempfd = -1; goto done; --- 272,278 ---- error(0, "mmbox.update_index: Failed lock temp file %s: error = %s\n", fbuf, strerror(errno)); ! unlock_and_close(tempfd); tempfd = -1; goto done; *************** *** 284,290 **** fbuf, strerror(errno)); ! close(tempfd); tempfd = -1; goto done; } --- 284,290 ---- fbuf, strerror(errno)); ! unlock_and_close(tempfd); tempfd = -1; goto done; } *************** *** 434,442 **** octstr_replace(sdf, octstr_imm("/"), octstr_imm("-")); done: if (dfd > 0) ! close(dfd); if (ifd > 0) ! close(ifd); if (s) octstr_destroy(s); --- 434,442 ---- octstr_replace(sdf, octstr_imm("/"), octstr_imm("-")); done: if (dfd > 0) ! unlock_and_close(dfd); if (ifd > 0) ! unlock_and_close(ifd); if (s) octstr_destroy(s); *************** *** 513,519 **** s = mms_tobinary(m); msize = octstr_len(s); ! octstr_write_to_socket(tmpfd, s); rename(octstr_get_cstr(ftmp), octstr_get_cstr(fname)); close(tmpfd); --- 513,519 ---- s = mms_tobinary(m); msize = octstr_len(s); ! octstr_write_to_socket(tmpfd, s); rename(octstr_get_cstr(ftmp), octstr_get_cstr(fname)); close(tmpfd); *************** *** 529,535 **** done: if (ifd > 0) ! close(ifd); if (fname) octstr_destroy(fname); --- 529,535 ---- done: if (ifd > 0) ! unlock_and_close(ifd); if (fname) octstr_destroy(fname); *************** *** 588,594 **** res = 0; done: if (ifd > 0) ! close(ifd); if (fname) octstr_destroy(fname); --- 588,594 ---- res = 0; done: if (ifd > 0) ! unlock_and_close(ifd); if (fname) octstr_destroy(fname); *************** *** 708,714 **** close(tmpfd); if (ifd > 0) ! close(ifd); if (flags) gwlist_destroy(flags, (gwlist_item_destructor_t *)octstr_destroy); --- 708,714 ---- close(tmpfd); if (ifd > 0) ! unlock_and_close(ifd); if (flags) gwlist_destroy(flags, (gwlist_item_destructor_t *)octstr_destroy); *************** *** 748,754 **** *msize = 0; done: if (ifd > 0) ! close(ifd); if (fname) octstr_destroy(fname); --- 748,754 ---- *msize = 0; done: if (ifd > 0) ! unlock_and_close(ifd); if (fname) octstr_destroy(fname); *************** *** 805,811 **** close(tmpfd); if (ifd > 0) ! close(ifd); return ret; } --- 805,811 ---- close(tmpfd); if (ifd > 0) ! unlock_and_close(ifd); return ret; } diff -rc mbuni-1.4.0_orig/mmlib/mms_queue.c mbuni-1.4.0/mmlib/mms_queue.c *** mbuni-1.4.0_orig/mmlib/mms_queue.c Thu Jul 10 07:43:38 2008 --- mbuni-1.4.0/mmlib/mms_queue.c Tue Dec 8 04:38:41 2009 *************** *** 21,28 **** #include <ctype.h> #ifdef SunOS #include <strings.h> - #include <fcntl.h> #endif #include <dirent.h> #include "mms_queue.h" --- 21,28 ---- #include <ctype.h> #ifdef SunOS #include <strings.h> #endif + #include <fcntl.h> #include <dirent.h> #include "mms_queue.h" *************** *** 202,212 **** strncpy(xqf, octstr_get_cstr(fname), sizeof xqf); if ((fd = open(octstr_get_cstr(fname), O_RDONLY)) < 0) { octstr_destroy(fname); return NULL; } else if (mm_lockfile(fd, octstr_get_cstr(fname), shouldblock) != 0) { ! close(fd); octstr_destroy(fname); return NULL; } --- 202,216 ---- strncpy(xqf, octstr_get_cstr(fname), sizeof xqf); + #ifdef SunOS /* fcntl WRLCK requires writablity */ + if ((fd = open(octstr_get_cstr(fname), O_RDWR)) < 0) { + #else if ((fd = open(octstr_get_cstr(fname), O_RDONLY)) < 0) { + #endif octstr_destroy(fname); return NULL; } else if (mm_lockfile(fd, octstr_get_cstr(fname), shouldblock) != 0) { ! unlock_and_close(fd); octstr_destroy(fname); return NULL; } *************** *** 552,561 **** error(0, "mms_queuewrite: Failed to rename %s to %s: error = %s\n", octstr_get_cstr(qfname), octstr_get_cstr(tfname), strerror(errno)); ! close(fd); /* Close new one, keep old one. */ res = -1; } else { /* On success, new descriptor replaces old one and we close old one. */ ! close(qfs->fd); qfs->fd = fd; } octstr_destroy(qfname); --- 556,565 ---- error(0, "mms_queuewrite: Failed to rename %s to %s: error = %s\n", octstr_get_cstr(qfname), octstr_get_cstr(tfname), strerror(errno)); ! unlock_and_close(fd); /* Close new one, keep old one. */ res = -1; } else { /* On success, new descriptor replaces old one and we close old one. */ ! unlock_and_close(qfs->fd); qfs->fd = fd; } octstr_destroy(qfname); *************** *** 619,625 **** if (fd >= 0 && mm_lockfile(fd,ctmp,1) != 0) { unlink(ctmp); ! close(fd); fd = -1; } octstr_destroy(tmp); --- 623,629 ---- if (fd >= 0 && mm_lockfile(fd,ctmp,1) != 0) { unlink(ctmp); ! unlock_and_close(fd); fd = -1; } octstr_destroy(tmp); *************** *** 648,654 **** dfname = octstr_format("%s/%s%s", mms_queuedir, subdir, df); fd = open(octstr_get_cstr(dfname), ! O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP); if (fd < 0) { error(0, "mms_queuadd: Failed to open data file %s: error = %s\n", octstr_get_cstr(dfname), strerror(errno)); --- 652,658 ---- dfname = octstr_format("%s/%s%s", mms_queuedir, subdir, df); fd = open(octstr_get_cstr(dfname), ! O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP); if (fd < 0) { error(0, "mms_queuadd: Failed to open data file %s: error = %s\n", octstr_get_cstr(dfname), strerror(errno)); *************** *** 793,799 **** snprintf(fname, -1 + sizeof fname, "%s/%s%s", qfs->dir, qfs->subdir, qfs->name); unlink(fname); } ! close(qfs->fd); /* close and unlock now that we have deleted it. */ mms_queue_free_envelope(e); --- 797,803 ---- snprintf(fname, -1 + sizeof fname, "%s/%s%s", qfs->dir, qfs->subdir, qfs->name); unlink(fname); } ! unlock_and_close(qfs->fd); /* close and unlock now that we have deleted it. */ mms_queue_free_envelope(e); diff -rc mbuni-1.4.0_orig/mmlib/mms_util.c mbuni-1.4.0/mmlib/mms_util.c *** mbuni-1.4.0_orig/mmlib/mms_util.c Wed Jul 9 04:19:42 2008 --- mbuni-1.4.0/mmlib/mms_util.c Tue Dec 8 04:24:49 2009 *************** *** 20,26 **** --- 20,29 ---- #ifdef SunOS #include <fcntl.h> + #include <pthread.h> + #include <sys/types.h> #endif + #include <sys/stat.h> #include <errno.h> #include <sys/types.h> *************** *** 887,911 **** } ! static int lockfile(int fd, int shouldblock) { - int n, stop; #ifdef SunOS ! int flg = shouldblock ? F_SETLKW : F_SETLK; ! flock_t lock; #else unsigned flg = shouldblock ? 0 : LOCK_NB; ! #endif do { - #ifdef SunOS - lock.l_whence = SEEK_SET; - lock.l_start = 0; - lock.l_len = 0; - lock.l_type = F_WRLCK; - n = fcntl(fd, flg, &lock); - #else n = flock(fd, LOCK_EX|flg); ! #endif if (n < 0) { if (errno == EINTR) stop = 0; --- 890,1088 ---- } ! /* Compare a file_lock(lhs) to the file_key(rhs) ! and see if they match ! */ ! int file_lock_inode_cmp(void *_lhs, void *_rhs); ! ! /* Each file gets a condition, there is only a single file_loc ! for each inode number. Assumes a uni ! */ ! typedef struct { ! dev_t dev; ! ino_t inode; ! } file_key; ! ! typedef struct { ! file_key key; ! pthread_cond_t condition; ! int fd; ! } file_lock; ! ! static List *openFileList = NULL; ! static pthread_mutex_t listMutex = PTHREAD_MUTEX_INITIALIZER; ! ! void release_file_lock(int fd, file_key *key) { ! debug("mm_util",0,"----->Locked"); ! pthread_mutex_lock(&listMutex); ! ! if (openFileList == NULL) { ! openFileList = (List *)gwlist_create(); ! } ! ! file_lock *item = (file_lock*)gwlist_search(openFileList, key, file_lock_inode_cmp); ! if (item && item->fd == fd) { ! /* we own the lock */ ! gwlist_delete_equal(openFileList, item); ! pthread_cond_broadcast(&item->condition); ! pthread_cond_destroy(&item->condition); ! gw_free(item); ! } ! debug("mm_util",0,"<-----UnLocked"); ! pthread_mutex_unlock(&listMutex); ! } ! ! int unlock_and_close(int fd) { ! #ifdef SunOS ! struct stat buf; ! if (fstat(fd, &buf)) { ! perror("Unable to fstat file for lock"); ! return close(fd); ! } ! ! file_key key; ! key.inode = buf.st_ino; ! key.dev = buf.st_dev; ! ! release_file_lock(fd, &key); ! #endif ! ! return close(fd); ! } ! ! int unlock_and_fclose(FILE *fp) { ! #ifdef SunOS ! int fd = fileno(fp); ! struct stat buf; ! if (fstat(fd, &buf)) { ! perror("Unable to fstat file for lock"); ! return fclose(fp); ! } ! ! file_key key; ! key.inode = buf.st_ino; ! key.dev = buf.st_dev; ! ! release_file_lock(fd, &key); ! #endif ! return fclose(fp); ! } ! ! /* Compare a file_lock(lhs) to the file_key(rhs) ! and see if they match ! */ ! int file_lock_inode_cmp(void *_lhs, void *_rhs) { ! file_key *rhs = (file_key*)_rhs; ! file_lock *lhs = (file_lock *)_lhs; ! ! return ( ! lhs && ! lhs->key.inode == rhs->inode && ! lhs->key.dev == rhs->dev ! ); ! } ! ! int sun_lockfile(int fd, int shouldblock) { #ifdef SunOS ! int n, stop; ! int flg = shouldblock ? F_SETLKW : F_SETLK; ! flock_t lock; ! ! struct stat buf; ! if (fstat(fd, &buf)) { ! int e = errno; ! perror("Unable to fstat file for lock"); ! errno = e; ! return(-1); ! } ! ! file_key key; ! key.inode = buf.st_ino; ! key.dev = buf.st_dev; ! ! debug("mm_util",0,"----->Locked"); ! pthread_mutex_lock(&listMutex); ! ! if (openFileList == NULL) { ! openFileList = (List *)gwlist_create(); ! } ! ! /* See if the inode exists in the list */ ! file_lock *item = NULL; ! do { ! item = (file_lock*)gwlist_search(openFileList, &key, file_lock_inode_cmp); ! if (item) { ! /* It exists, that means that someone has already locked the file */ ! if (!shouldblock) { ! n = -1; ! debug("mm_util",0,"<-----UnLocked"); ! pthread_mutex_unlock(&listMutex); ! errno = EWOULDBLOCK; ! return n; ! } ! ! pthread_cond_wait(&item->condition, &listMutex); ! /* O.k. we've got the file, but now item is invalid, ! the unlock_and_close removes it. ! */ ! } ! } while (item != NULL); ! ! /* No one else has locked the file, create the condition for ! anyone else. ! */ ! item = (file_lock*)gw_malloc(sizeof(file_lock)); ! item->key.inode = key.inode; ! item->key.dev = key.dev; ! item->fd = fd; ! pthread_cond_init(&item->condition, NULL); ! gwlist_append(openFileList, item); ! ! /* Release the global lock so that we don't block the ! entire system waiting for fnctl to return ! */ ! debug("mm_util",0,"<-----UnLocked"); ! pthread_mutex_unlock(&listMutex); ! ! do { ! lock.l_whence = SEEK_SET; ! lock.l_start = 0; ! lock.l_len = 0; ! lock.l_type = F_WRLCK; ! n = fcntl(fd, flg, &lock); ! if (n < 0) { ! if (errno == EINTR) ! stop = 0; ! else ! stop = 1; ! } else ! stop = 1; ! } while (!stop); ! ! /* If we failed to get the fcntl lock, then we need to ! release the local lock */ ! if (n != 0) { ! release_file_lock(fd, &key); ! } ! ! return (n == 0) ? 0 : errno; ! #else ! panic(0, "Attempt to call sun_lockfile on a non-solaris system"); ! #endif ! } ! ! int lockfile(int fd, int shouldblock) ! { ! #ifdef SunOS ! return sun_lockfile(fd, shouldblock); #else + int n, stop; unsigned flg = shouldblock ? 0 : LOCK_NB; ! do { n = flock(fd, LOCK_EX|flg); ! if (n < 0) { if (errno == EINTR) stop = 0; *************** *** 916,921 **** --- 1093,1099 ---- } while (!stop); return (n == 0) ? 0 : errno; + #endif } static int check_lock(int fd, char *fname) *************** *** 943,948 **** --- 1121,1132 ---- { int ret = lockfile(fd,shouldblock); + if (ret && errno != EWOULDBLOCK) { + debug("mm_util", 0, "Unable to lock '%s', error= %d, %s, shouldblock=%d", + fname, errno, strerror(errno), shouldblock); + perror("Unable to lock file"); + } + if (ret != 0 || (ret = check_lock(fd,fname)) != 0) return ret; diff -rc mbuni-1.4.0_orig/mmlib/mms_util.h mbuni-1.4.0/mmlib/mms_util.h *** mbuni-1.4.0_orig/mmlib/mms_util.h Mon Jul 7 06:23:11 2008 --- mbuni-1.4.0/mmlib/mms_util.h Tue Dec 8 03:38:44 2009 *************** *** 142,147 **** --- 142,154 ---- /* Returns true if the character is printable or space */ int _mms_gw_isprint(int c); + int lockfile(int fd, int shouldblock); + /* + * unlock_and_fclose/unlock_and_close are wrappers around fclose/close + * needed to maintain the state of the global list on Solaris. + */ + int unlock_and_fclose(FILE *fp); + int unlock_and_close(int fd); /* Special form of cfg_get which returns zero-length string when there is nothing. */ Octstr *_mms_cfg_getx(mCfgGrp *grp, Octstr *item); diff -rc mbuni-1.4.0_orig/mmsbox/dlr.c mbuni-1.4.0/mmsbox/dlr.c *** mbuni-1.4.0_orig/mmsbox/dlr.c Fri Dec 21 10:10:06 2007 --- mbuni-1.4.0/mmsbox/dlr.c Tue Dec 8 03:13:31 2009 *************** *** 72,78 **** p, strerror(errno)); break; } else if (mm_lockfile(fd, p, 1) != 0) { ! close(fd); fd = -1; } while (i++ < MAXTRIES && fd < 0); --- 72,78 ---- p, strerror(errno)); break; } else if (mm_lockfile(fd, p, 1) != 0) { ! unlock_and_close(fd); fd = -1; } while (i++ < MAXTRIES && fd < 0); *************** *** 92,98 **** if (fd >= 0) { Octstr *x = octstr_format("%S %S", transid ? transid : octstr_imm("x"), dlr_url); /* better have no spaces in transid! */ octstr_write_data(x, fd, 0); ! close(fd); octstr_destroy(x); } } --- 92,98 ---- if (fd >= 0) { Octstr *x = octstr_format("%S %S", transid ? transid : octstr_imm("x"), dlr_url); /* better have no spaces in transid! */ octstr_write_data(x, fd, 0); ! unlock_and_close(fd); octstr_destroy(x); } } *************** *** 106,112 **** Octstr *s = octstr_read_pipe(f); int i, ret; ! fclose(f); if (s && octstr_len(s) == 0) { ret = -1; } else if ((i = octstr_search_char(s, ' ', 0)) >= 0) { --- 106,112 ---- Octstr *s = octstr_read_pipe(f); int i, ret; ! unlock_and_fclose(f); if (s && octstr_len(s) == 0) { ret = -1; } else if ((i = octstr_search_char(s, ' ', 0)) >= 0) { *************** *** 118,124 **** octstr_destroy(s); return ret; } else if (fd >= 0) ! close(fd); return -1; } --- 118,124 ---- octstr_destroy(s); return ret; } else if (fd >= 0) ! unlock_and_close(fd); return -1; } *************** *** 130,134 **** if (fname) unlink(octstr_get_cstr(fname)); if (fd >= 0) ! close(fd); } --- 130,134 ---- if (fname) unlink(octstr_get_cstr(fname)); if (fd >= 0) ! unlock_and_close(fd); } diff -rc mbuni-1.4.0_orig/mmsbox/mmsbox.c mbuni-1.4.0/mmsbox/mmsbox.c *** mbuni-1.4.0_orig/mmsbox/mmsbox.c Thu Jul 10 09:33:42 2008 --- mbuni-1.4.0/mmsbox/mmsbox.c Sun Dec 6 23:33:41 2009 *************** *** 607,613 **** --- 607,624 ---- mms_cfg_destroy(cfg); + #ifdef SA_RESTART + { + struct sigaction nact; + + memset(&nact, 0, sizeof(nact)); + nact.sa_handler = relog_now; + nact.sa_flags = SA_RESTART; + sigaction(SIGHUP, &nact, (struct sigaction *)0); + } + #else signal(SIGHUP, relog_now); + #endif signal(SIGTERM, quit_now); signal(SIGPIPE,SIG_IGN); /* Ignore pipe errors. They kill us sometimes for nothing*/ diff -rc mbuni-1.4.0_orig/mmsc/mms_billing_shell.c mbuni-1.4.0/mmsc/mms_billing_shell.c *** mbuni-1.4.0_orig/mmsc/mms_billing_shell.c Wed Aug 29 12:23:39 2007 --- mbuni-1.4.0/mmsc/mms_billing_shell.c Thu Sep 25 08:13:05 2008 *************** *** 12,17 **** --- 12,18 ---- */ #include <stdio.h> #include <stdlib.h> + #include <wait.h> #include "mms_billing.h" diff -rc mbuni-1.4.0_orig/mmsc/mmsproxy.c mbuni-1.4.0/mmsc/mmsproxy.c *** mbuni-1.4.0_orig/mmsc/mmsproxy.c Thu Jul 10 09:37:03 2008 --- mbuni-1.4.0/mmsc/mmsproxy.c Sun Dec 6 23:32:43 2009 *************** *** 105,111 **** --- 105,122 ---- panic(0, "No global MMSC configuration!"); + #ifdef SA_RESTART + { + struct sigaction nact; + + memset(&nact, 0, sizeof(nact)); + nact.sa_handler = relog_now; + nact.sa_flags = SA_RESTART; + sigaction(SIGHUP, &nact, (struct sigaction *)0); + } + #else signal(SIGHUP, relog_now); + #endif signal(SIGTERM, quit_now); /* Start cache engine. */ diff -rc mbuni-1.4.0_orig/mmsc/mmsrelay.c mbuni-1.4.0/mmsc/mmsrelay.c *** mbuni-1.4.0_orig/mmsc/mmsrelay.c Thu Jul 10 09:32:42 2008 --- mbuni-1.4.0/mmsc/mmsrelay.c Sun Dec 6 23:33:11 2009 *************** *** 71,77 **** --- 71,88 ---- mms_start_profile_engine(octstr_get_cstr(settings->ua_profile_cache_dir)); #endif + #ifdef SA_RESTART + { + struct sigaction nact; + + memset(&nact, 0, sizeof(nact)); + nact.sa_handler = relog_now; + nact.sa_flags = SA_RESTART; + sigaction(SIGHUP, &nact, (struct sigaction *)0); + } + #else signal(SIGHUP, relog_now); + #endif signal(SIGTERM, quit_now); signal(SIGPIPE,SIG_IGN); /* Ignore pipe errors. They kill us sometimes for nothing*/
_______________________________________________ Devel mailing list Devel@mbuni.org http://lists.mbuni.org/mailman/listinfo/devel