/* Unix specific code of release_dotlock. */ static int dotlock_release_unix (dotlock_t h) { int pid, same_node; pid = read_lockfile (h, &same_node); if ( pid == -1 ) { my_error_0 ("release_dotlock: lockfile error\n"); return -1; } if ( pid != getpid() || !same_node ) { my_error_1 ("release_dotlock: not our lock (pid=%d)\n", pid); return -1; } if ( unlink( h->lockname ) ) { my_error_1 ("release_dotlock: error removing lockfile `%s'\n", h->lockname); return -1; } /* Fixme: As an extra check we could check whether the link count is now really at 1. */ return 0; }
static duk_ret_t test_vararg(duk_context *ctx, void *udata) { (void) udata; duk_set_top(ctx, 0); my_error_1(ctx, DUK_ERR_RANGE_ERROR, "my error %d %d %s", 123, 234, "foobar"); printf("final top: %ld\n", (long) duk_get_top(ctx)); return 0; }
/* Unix specific code of make_dotlock. Returns 0 on success and -1 on error. */ static int dotlock_take_unix (dotlock_t h, long timeout) { int wtime = 0; int sumtime = 0; int pid; int lastpid = -1; int ownerchanged; const char *maybe_dead=""; int same_node; again: if (h->use_o_excl) { /* No hardlink support - use open(O_EXCL). */ int fd; do { jnlib_set_errno (0); fd = open (h->lockname, O_WRONLY|O_CREAT|O_EXCL, S_IRUSR|S_IRGRP|S_IROTH|S_IWUSR ); } while (fd == -1 && errno == EINTR); if (fd == -1 && errno == EEXIST) ; /* Lock held by another process. */ else if (fd == -1) { my_error_2 ("lock not made: open(O_EXCL) of `%s' failed: %s\n", h->lockname, strerror (errno)); return -1; } else { char pidstr[16]; snprintf (pidstr, sizeof pidstr, "%10d\n", (int)getpid()); if (write (fd, pidstr, 11 ) == 11 && write (fd, h->tname + h->nodename_off,h->nodename_len) == h->nodename_len && write (fd, "\n", 1) == 1 && !close (fd)) { h->locked = 1; return 0; } /* Write error. */ my_error_2 ("lock not made: writing to `%s' failed: %s\n", h->lockname, strerror (errno)); close (fd); unlink (h->lockname); return -1; } } else /* Standard method: Use hardlinks. */ { struct stat sb; link (h->tname, h->lockname); if (stat (h->tname, &sb)) { my_error_1 ("lock not made: Oops: stat of tmp file failed: %s\n", strerror (errno)); /* In theory this might be a severe error: It is possible that link succeeded but stat failed due to changed permissions. We can't do anything about it, though. */ return -1; } if (sb.st_nlink == 2) { h->locked = 1; return 0; /* Okay. */ } } /* Check for stale lock files. */ if ( (pid = read_lockfile (h, &same_node)) == -1 ) { if ( errno != ENOENT ) { my_info_0 ("cannot read lockfile\n"); return -1; } my_info_0 ("lockfile disappeared\n"); goto again; } else if ( pid == getpid() && same_node ) { my_info_0 ("Oops: lock already held by us\n"); h->locked = 1; return 0; /* okay */ } else if ( same_node && kill (pid, 0) && errno == ESRCH ) { /* Note: It is unlikley that we get a race here unless a pid is reused too fast or a new process with the same pid as the one of the stale file tries to lock right at the same time as we. */ my_info_1 (_("removing stale lockfile (created by %d)\n"), pid); unlink (h->lockname); goto again; } if (lastpid == -1) lastpid = pid; ownerchanged = (pid != lastpid); if (timeout) { struct timeval tv; /* Wait until lock has been released. We use increasing retry intervals of 50ms, 100ms, 200ms, 400ms, 800ms, 2s, 4s and 8s but reset it if the lock owner meanwhile changed. */ if (!wtime || ownerchanged) wtime = 50; else if (wtime < 800) wtime *= 2; else if (wtime == 800) wtime = 2000; else if (wtime < 8000) wtime *= 2; if (timeout > 0) { if (wtime > timeout) wtime = timeout; timeout -= wtime; } sumtime += wtime; if (sumtime >= 1500) { sumtime = 0; my_info_3 (_("waiting for lock (held by %d%s) %s...\n"), pid, maybe_dead, maybe_deadlock(h)? _("(deadlock?) "):""); } tv.tv_sec = wtime / 1000; tv.tv_usec = (wtime % 1000) * 1000; select (0, NULL, NULL, NULL, &tv); goto again; } jnlib_set_errno (EACCES); return -1; }