60
/* The object describing a lock. */
57
61
struct dotlock_handle
59
63
struct dotlock_handle *next;
60
char *tname; /* Name of lockfile template. */
64
char *lockname; /* Name of the actual lockfile. */
65
int locked; /* Lock status. */
66
int disable; /* If true, locking is disabled. */
68
#ifdef HAVE_DOSISH_SYSTEM
69
HANDLE lockhd; /* The W32 handle of the lock file. */
71
char *tname; /* Name of the lockfile template. */
61
72
size_t nodename_off; /* Offset in TNAME of the nodename part. */
62
size_t nodename_len; /* Length of the nodename part. */
63
char *lockname; /* Name of the real lockfile. */
64
int locked; /* Lock status. */
65
int disable; /* When true, locking is disabled. */
73
size_t nodename_len; /* Length of the nodename part. */
74
#endif /* HAVE_DOSISH_SYSTEM */
78
/* A list of of all lock handles. */
69
79
static volatile DOTLOCK all_lockfiles;
81
/* If this has the value true all locking is disabled. */
70
82
static int never_lock;
85
/* Local protototypes. */
86
#ifndef HAVE_DOSISH_SYSTEM
72
87
static int read_lockfile (DOTLOCK h, int *same_node);
88
#endif /*!HAVE_DOSISH_SYSTEM*/
93
/* Entirely disable all locking. This function should be called
94
before any locking is done. It may be called right at startup of
95
the process as it only sets a global value. */
75
97
disable_dotlock(void)
81
* Create a lockfile with the given name and return an object of
82
* type DOTLOCK which may be used later to actually do the lock.
83
* A cleanup routine gets installed to cleanup left over locks
84
* or other files used together with the lock mechanism.
85
* Although the function is called dotlock, this does not necessarily
86
* mean that real lockfiles are used - the function may decide to
87
* use fcntl locking. Calling the function with NULL only install
88
* the atexit handler and maybe used to assure that the cleanup
89
* is called after all other atexit handlers.
91
* Notes: This function creates a lock file in the same directory
92
* as file_to_lock with the name "file_to_lock.lock"
93
* A temporary file ".#lk.<hostname>.pid[.threadid] is used.
94
* This function does nothing for Windoze.
104
/* Create a lockfile for a file name FILE_TO_LOCK and returns an
105
object of type DOTLOCK which may be used later to actually acquire
106
the lock. A cleanup routine gets installed to cleanup left over
107
locks or other files used internally by the lock mechanism.
109
Calling this function with NULL does only install the atexit
110
handler and may thus be used to assure that the cleanup is called
111
after all other atexit handlers.
113
This function creates a lock file in the same directory as
114
FILE_TO_LOCK using that name and a suffix of ".lock". Note that on
115
POSIX systems a temporary file ".#lk.<hostname>.pid[.threadid] is
118
The function returns an new handle which needs to be released using
119
destroy_dotlock but gets also released at the termination of the
120
process. On error NULL is returned.
97
create_dotlock( const char *file_to_lock )
123
create_dotlock (const char *file_to_lock)
99
125
static int initialized;
127
#ifndef HAVE_DOSISH_SYSTEM
103
130
const char *nodename;
104
131
const char *dirpart;
106
#ifndef HAVE_DOSISH_SYSTEM
107
133
struct utsname utsbuf;
110
137
if ( !initialized )
112
atexit( dotlock_remove_lockfiles );
139
atexit (dotlock_remove_lockfiles);
115
143
if ( !file_to_lock )
116
144
return NULL; /* Only initialization was requested. */
118
h = jnlib_xcalloc ( 1, sizeof *h );
146
h = jnlib_calloc (1, sizeof *h);
122
153
#ifdef _REENTRANT
163
199
h->next = all_lockfiles;
164
200
all_lockfiles = h;
166
h->tname = jnlib_xmalloc ( dirpartlen + 6+30+ strlen(nodename) + 11 );
202
tnamelen = dirpartlen + 6 + 30 + strlen(nodename) + 10;
203
h->tname = jnlib_malloc (tnamelen + 1);
206
all_lockfiles = h->next;
167
210
h->nodename_len = strlen (nodename);
168
212
#ifndef __riscos__
169
sprintf (h->tname, "%.*s/.#lk%p.", dirpartlen, dirpart, h );
213
snprintf (h->tname, tnamelen, "%.*s/.#lk%p.", dirpartlen, dirpart, h );
170
214
h->nodename_off = strlen (h->tname);
171
sprintf (h->tname+h->nodename_off, "%s.%d", nodename, (int)getpid ());
215
snprintf (h->tname+h->nodename_off, tnamelen - h->nodename_off,
216
"%s.%d", nodename, (int)getpid ());
172
217
#else /* __riscos__ */
173
sprintf (h->tname, "%.*s.lk%p/", dirpartlen, dirpart, h );
218
snprintf (h->tname, tnamelen, "%.*s.lk%p/", dirpartlen, dirpart, h );
174
219
h->nodename_off = strlen (h->tname);
175
sprintf (h->tname+h->nodename_off, "%s/%d", nodename, (int)getpid () );
220
snprintf (h->tname+h->nodename_off, tnamelen - h->modename_off,
221
"%s/%d", nodename, (int)getpid () );
176
222
#endif /* __riscos__ */
204
250
# ifdef _REENTRANT
205
251
/* release mutex */
207
#endif /* !HAVE_DOSISH_SYSTEM */
208
h->lockname = jnlib_xmalloc ( strlen (file_to_lock) + 6 );
209
strcpy (stpcpy(h->lockname, file_to_lock), EXTSEP_S "lock");
253
h->lockname = jnlib_malloc ( strlen (file_to_lock) + 6 );
256
all_lockfiles = h->next;
258
jnlib_free (h->tname);
262
strcpy (stpcpy (h->lockname, file_to_lock), EXTSEP_S "lock");
212
266
all_lockfiles = h->next;
213
267
# ifdef _REENTRANT
214
268
/* fixme: release mutex */
216
log_error ( "error writing to `%s': %s\n", h->tname, strerror(errno) );
219
jnlib_free(h->tname);
270
log_error ( _("error writing to `%s': %s\n"), h->tname, strerror(errno) );
273
jnlib_free (h->tname);
277
#else /* HAVE_DOSISH_SYSTEM */
279
/* The Windows version does not need a temporary file but uses the
280
plain lock file along with record locking. We create this file
281
here so that we later do only need to do the file locking. For
282
error reporting it is useful to keep the name of the file in the
284
h->next = all_lockfiles;
287
h->lockname = jnlib_malloc ( strlen (file_to_lock) + 6 );
290
all_lockfiles = h->next;
294
strcpy (stpcpy(h->lockname, file_to_lock), EXTSEP_S "lock");
296
/* If would be nice if we would use the FILE_FLAG_DELETE_ON_CLOSE
297
along with FILE_SHARE_DELETE but that does not work due to a race
298
condition: Despite the OPEN_ALWAYS flag CreateFile may return an
299
error and we can't reliable create/open the lock file unless we
300
would wait here until it works - however there are other valid
301
reasons why a lock file can't be created and thus the process
302
would not stop as expected but spin til until Windows crashes.
303
Our solution is to keep the lock file open; that does not
305
h->lockhd = CreateFile (h->lockname,
306
GENERIC_READ|GENERIC_WRITE,
307
FILE_SHARE_READ|FILE_SHARE_WRITE,
308
NULL, OPEN_ALWAYS, 0, NULL);
309
if (h->lockhd == INVALID_HANDLE_VALUE)
311
log_error (_("can't create `%s': %s\n"), h->lockname, w32_strerror (-1));
312
all_lockfiles = h->next;
313
jnlib_free (h->lockname);
319
#endif /* HAVE_DOSISH_SYSTEM */
323
/* Destroy the local handle H and release the lock. */
226
325
destroy_dotlock ( DOTLOCK h )
228
#ifndef HAVE_DOSISH_SYSTEM
332
/* First remove the handle from our global list of all locks. */
333
for (hprev=NULL, htmp=all_lockfiles; htmp; hprev=htmp, htmp=htmp->next)
337
hprev->next = htmp->next;
339
all_lockfiles = htmp->next;
344
/* Then destroy the lock. */
233
/* First remove the handle from our global list of all locks. */
234
for (hprev=NULL, htmp=all_lockfiles; htmp; hprev=htmp, htmp=htmp->next)
238
hprev->next = htmp->next;
240
all_lockfiles = htmp->next;
245
/* Second destroy the lock. */
347
#ifdef HAVE_DOSISH_SYSTEM
248
if (h->locked && h->lockname)
249
unlink (h->lockname);
252
jnlib_free (h->tname);
253
jnlib_free (h->lockname);
350
UnlockFile (h->lockhd, 0, 0, 1, 0);
352
CloseHandle (h->lockhd);
353
#else /* !HAVE_DOSISH_SYSTEM */
354
if (h->locked && h->lockname)
355
unlink (h->lockname);
358
jnlib_free (h->tname);
359
#endif /* HAVE_DOSISH_SYSTEM */
360
jnlib_free (h->lockname);
257
#endif /*!HAVE_DOSISH_SYSTEM*/
366
#ifndef HAVE_DOSISH_SYSTEM
263
368
maybe_deadlock( DOTLOCK h )
276
* Do a lock on H. A TIMEOUT of 0 returns immediately, -1 waits
277
* forever (hopefully not), other values are reserved (should then be
278
* timeouts in milliseconds). Returns: 0 on success
379
#endif /*!HAVE_DOSISH_SYSTEM*/
383
/* Do a lock on H. A TIMEOUT of 0 returns immediately, -1 waits
384
forever (hopefully not), other values are reserved (should then be
385
timeouts in milliseconds). Returns: 0 on success */
281
make_dotlock( DOTLOCK h, long timeout )
387
make_dotlock ( DOTLOCK h, long timeout )
283
#ifdef HAVE_DOSISH_SYSTEM
390
#ifndef HAVE_DOSISH_SYSTEM
287
392
const char *maybe_dead="";
394
#endif /*!HAVE_DOSISH_SYSTEM*/
291
396
if ( h->disable )
292
397
return 0; /* Locks are completely disabled. Return success. */
483
#else /*HAVE_DOSISH_SYSTEM*/
486
if (LockFile (h->lockhd, 0, 0, 1, 0))
491
w32err = GetLastError ();
492
if (w32err != ERROR_LOCK_VIOLATION)
494
log_error (_("lock `%s' not made: %s\n"),
495
h->lockname, w32_strerror (w32err));
501
/* Wait until lock has been released. */
502
log_info (_("waiting for lock %s...\n"), h->lockname);
503
Sleep ((1 + backoff)*1000);
509
#endif /*HAVE_DOSISH_SYSTEM*/
379
#endif /* !HAVE_DOSISH_SYSTEM */
385
* Returns: 0 := success
515
/* Release a lock. Returns 0 on success. */
388
517
release_dotlock( DOTLOCK h )
390
#ifdef HAVE_DOSISH_SYSTEM
519
#ifndef HAVE_DOSISH_SYSTEM
393
520
int pid, same_node;
395
523
/* To avoid atexit race conditions we first check whether there are
396
524
any locks left. It might happen that another atexit handler
405
533
if ( !h->locked )
407
log_debug("oops, `%s' is not locked\n", h->lockname );
535
log_debug("Oops, `%s' is not locked\n", h->lockname);
539
#ifdef HAVE_DOSISH_SYSTEM
540
if (!UnlockFile (h->lockhd, 0, 0, 1, 0))
542
log_error ("release_dotlock: error removing lockfile `%s': %s\n",
543
h->lockname, w32_strerror (-1));
411
548
pid = read_lockfile (h, &same_node);
419
556
log_error( "release_dotlock: not our lock (pid=%d)\n", pid);
422
560
#ifndef __riscos__
423
561
if ( unlink( h->lockname ) )
425
log_error( "release_dotlock: error removing lockfile `%s'",
563
log_error ("release_dotlock: error removing lockfile `%s'\n",
567
/* Fixme: As an extra check we could check whether the link count is
429
569
#else /* __riscos__ */
430
if ( renamefile(h->lockname, h->tname) )
570
if ( renamefile (h->lockname, h->tname) )
432
log_error( "release_dotlock: error renaming lockfile `%s' to `%s'",
572
log_error ("release_dotlock: error renaming lockfile `%s' to `%s'\n",
433
573
h->lockname, h->tname);
436
576
#endif /* __riscos__ */
437
/* fixme: check that the link count is now 1 */
578
#endif /* !HAVE_DOSISH_SYSTEM */
440
#endif /* !HAVE_DOSISH_SYSTEM */
445
Read the lock file and return the pid, returns -1 on error. True
446
will be stored at SAME_NODE if the lock file has been created on
584
/* Read the lock file and return the pid, returns -1 on error. True
585
will be stored in the integer at address SAME_NODE if the lock file
586
has been created on the same node. */
587
#ifndef HAVE_DOSISH_SYSTEM
450
589
read_lockfile (DOTLOCK h, int *same_node )
452
#ifdef HAVE_DOSISH_SYSTEM
455
591
char buffer_space[10+1+70+1]; /* 70 is just an estimated value; node
456
592
name are usually shorter. */