Hi all,

yesterday I ran into the following problem. I use the apr_file_lock() function in conjunction with the APR_FOPEN_APPEND flag and under Linux everything is fine.

Under Windows any attempt to write to the opened and locked file I get a deadlock. This is due the fact that apr_file_write() creates an own lock with apr_file_lock() if the file was opened with the APR_FOPEN_APPEND flag.

First this is inconsistent through different operating systems Unix does not lock, Windows does lock the file in append mode. However, I think the locking in the Windows implementation is wrong. The user has to choose if he wants to lock the file or not!

To reproduce the behavior please compile and test the attached example!

Any comments? Should I file a bug report?

Regards,
Stefan

#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>

#include <apr-1/apr_file_io.h>

static
apr_file_t *locked_open(const char *name, apr_pool_t *pool, apr_int32_t flags)
{
   apr_status_t rc;
   apr_file_t *fp = NULL;

   if((rc = apr_file_open(&fp, name, (APR_FOPEN_CREATE|APR_FOPEN_BINARY|
				      APR_FOPEN_WRITE|flags),
			  APR_FPROT_OS_DEFAULT,
			  pool)) == APR_SUCCESS)
   {
      if((rc = apr_file_lock(fp, APR_FLOCK_EXCLUSIVE)) != APR_SUCCESS)
      {
	 apr_file_close(fp);
	 fp = NULL;
      }
   }

   if(rc != APR_SUCCESS)
      fprintf(stderr, "locked_open(%s): error %d\n", name, rc);
   return fp;
}

static
void locked_printf(apr_file_t *fp, const char *fmt, ...)
{
   apr_status_t rc;
   apr_size_t size;
   char buf[1024];
   va_list args;

   va_start(args, fmt);
   apr_vsnprintf(buf, sizeof(buf), fmt, args);
   va_end(args);

   size = strlen(buf);
   rc = apr_file_write(fp, buf, &size);
   if(rc != APR_SUCCESS)
      fprintf(stderr, "locked_printf(): error %d\n", rc);
}

static
void locked_close(apr_file_t *fp)
{
   apr_status_t rc;

   rc = apr_file_unlock(fp);
   if(rc != APR_SUCCESS)
      fprintf(stderr, "locked_close(): error %d\n", rc);

   rc = apr_file_close(fp);
   if(rc != APR_SUCCESS)
      fprintf(stderr, "locked_close(): error %d\n", rc);
}

int main(int argc, char *argv[])
{
   apr_file_t *wfp;
   apr_file_t *afp;
   apr_pool_t *pool;

   apr_initialize();

   if(apr_pool_create(&pool, NULL) != APR_SUCCESS)
   {
      fprintf(stderr, "%s: can't create memory pool\n", argv[0]);
      exit(1);
   }

   fprintf(stderr, "creating locked foo.log\n");
   if((wfp = locked_open("foo.log", pool, 0)) != NULL)
   {
      locked_printf(wfp, "%s: create and write file!\n", argv[0]);

      locked_close(wfp);
   }

   fprintf(stderr, "appending to locked foo.log\n");
   if((afp = locked_open("foo.log", pool, APR_FOPEN_APPEND)) != NULL)
   {
      /* deadlocks under Windows! */
      locked_printf(afp, "%s: create and append file!\n", argv[0]);

      locked_close(afp);
   }

   fprintf(stderr, "finished\n");
   apr_pool_destroy(pool);

   apr_terminate();

   return 0;
}

Reply via email to