static int apply_lock(int fd, int fcntltype, BOOL dofcntl, int fcntltime, BOOL doflock, int flocktime) { int yield = 0; int save_errno; struct flock lock_data; lock_data.l_type = fcntltype; lock_data.l_whence = lock_data.l_start = lock_data.l_len = 0; sigalrm_seen = FALSE; if (dofcntl) { if (fcntltime > 0) { os_non_restarting_signal(SIGALRM, sigalrm_handler); alarm(fcntltime); yield = fcntl(fd, F_SETLKW, &lock_data); save_errno = errno; alarm(0); errno = save_errno; } else yield = fcntl(fd, F_SETLK, &lock_data); if (yield < 0) printf("exim_lock: fcntl() failed: %s\n", strerror(errno)); } #ifndef NO_FLOCK if (doflock && (yield >= 0)) { int flocktype = (fcntltype == F_WRLCK)? LOCK_EX : LOCK_SH; if (flocktime > 0) { os_non_restarting_signal(SIGALRM, sigalrm_handler); alarm(flocktime); yield = flock(fd, flocktype); save_errno = errno; alarm(0); errno = save_errno; } else yield = flock(fd, flocktype | LOCK_NB); if (yield < 0) printf("exim_lock: flock() failed: %s\n", strerror(errno)); } #endif return yield; }
int main(int argc, char **argv) { char buffer[128]; int fd = fileno(stdin); int rc; printf("Testing restarting signal; wait for handler message, then type a line\n"); strcpy(buffer, "*** default ***\n"); os_restarting_signal(SIGALRM, sigalrm_handler); alarm(2); if ((rc = read(fd, buffer, sizeof(buffer))) < 0) printf("No data read\n"); else { buffer[rc] = 0; printf("Read: %s", buffer); } alarm(0); printf("Testing non-restarting signal; should read no data after handler message\n"); strcpy(buffer, "*** default ***\n"); os_non_restarting_signal(SIGALRM, sigalrm_handler); alarm(2); if ((rc = read(fd, buffer, sizeof(buffer))) < 0) printf("No data read\n"); else { buffer[rc] = 0; printf("Read: %s", buffer); } alarm(0); printf("Testing load averages (last test - ^C to kill)\n"); for (;;) { int avg; clock_t used; clock_t before = clock(); avg = os_getloadavg(); used = clock() - before; printf("cpu time = %.2f ", (double)used/REAL_CLOCK_TICK); if (avg < 0) { printf("load average not available\n"); break; } printf("load average = %.2f\n", (double)avg/1000.0); sleep(2); } return 0; }
static open_db * dbfn_open(uschar *spool, uschar *name, int flags, open_db *dbblock) { int rc; struct flock lock_data; BOOL read_only = flags == O_RDONLY; uschar buffer[256]; /* The first thing to do is to open a separate file on which to lock. This ensures that Exim has exclusive use of the database before it even tries to open it. If there is a database, there should be a lock file in existence. */ sprintf(CS buffer, "%s/db/%s.lockfile", spool, name); dbblock->lockfd = Uopen(buffer, flags, 0); if (dbblock->lockfd < 0) { printf("** Failed to open database lock file %s: %s\n", buffer, strerror(errno)); return NULL; } /* Now we must get a lock on the opened lock file; do this with a blocking lock that times out. */ lock_data.l_type = read_only? F_RDLCK : F_WRLCK; lock_data.l_whence = lock_data.l_start = lock_data.l_len = 0; sigalrm_seen = FALSE; os_non_restarting_signal(SIGALRM, sigalrm_handler); alarm(EXIMDB_LOCK_TIMEOUT); rc = fcntl(dbblock->lockfd, F_SETLKW, &lock_data); alarm(0); if (sigalrm_seen) errno = ETIMEDOUT; if (rc < 0) { printf("** Failed to get %s lock for %s: %s", ((flags & O_RDONLY) != 0)? "read" : "write", buffer, (errno == ETIMEDOUT)? "timed out" : strerror(errno)); (void)close(dbblock->lockfd); return NULL; } /* At this point we have an opened and locked separate lock file, that is, exclusive access to the database, so we can go ahead and open it. */ sprintf(CS buffer, "%s/db/%s", spool, name); EXIM_DBOPEN(buffer, flags, 0, &(dbblock->dbptr)); if (dbblock->dbptr == NULL) { printf("** Failed to open DBM file %s for %s:\n %s%s\n", buffer, read_only? "reading" : "writing", strerror(errno), #ifdef USE_DB " (or Berkeley DB error while opening)" #else "" #endif ); (void)close(dbblock->lockfd); return NULL; } return dbblock; }