apr-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Chris Darroch <chr...@pearsoncmg.com>
Subject opening named pipes
Date Tue, 18 Dec 2012 21:41:41 GMT
Hi --

   I recently needed to wire up httpd's rotatelogs to a named pipe (a FIFO)
instead of to stdin.  For context, we have a non-httpd server process
configured to write to the pipe instead of a log file; further, this
server likes to intermittently open, write to, and close its various
log files.

   I wanted/needed to open the pipe in non-blocking mode, so rotatelogs
would start right away (we're using rotatelogs -cf) instead of blocking
until a writer process happened to open the pipe to write some log data.

   My first attempt was to open the pipe as a regular file using
apr_file_open(), then extract the fd with apr_os_file_get(), use it
to create an APR pipe with apr_os_pipe_put(), and then set the
non-blocking status with apr_file_pipe_timeout_set().  That doesn't
work with APR 1.4.x, though, because the initial file open lacks
O_NONBLOCK.

   With APR trunk I could use APR_FOPEN_NONBLOCK, but even so it's
a bit of a workaround for something which I thought would be simple.

   At any rate, here's what I ended up with, an apr_file_namedpipe_open()
call which tries to align with the usage of the 1.4.x APR_*_BLOCK flags
in apr_file_pipe_create_ex(), although all that's really needed is
a simple Boolean -- but we don't have APR_FOPEN_NONBLOCK in 1.4.x.

   Unlike the apr_file_open() trick I tried first, it won't let you
open a non-pipe by accident, and it will set the timeout and blocking
flags right away.

   I'm sure others can improve on this (e.g., using APR_FOPEN_NONBLOCK
instead of the APR_*_BLOCK values), and/or see reasons not to include it
(I didn't try a Windows version, for example).  But perhaps it'll help
the next person, at least.  I'll post my rotatelogs patch over on
dev@httpd in a moment.

Chris.

===================================================================
--- include/apr_file_io.h.orig	2012-12-18 13:15:01.000000000 -0800
+++ include/apr_file_io.h	2012-12-18 13:17:48.000000000 -0800
@@ -741,6 +741,33 @@
                                                   apr_pool_t *pool);
 
 /**
+ * Open a named pipe.
+ * @param file The opened file descriptor.
+ * @param fname The full path to the file (using / on all systems)
+ * @param flag Or'ed value of:
+ * <PRE>
+ *         APR_READ              open for reading
+ *         APR_WRITE             open for writing
+ * </PRE>
+ * @param blocking one of these values defined in apr_thread_proc.h:
+ * <pre>
+ *       APR_FULL_BLOCK
+ *       APR_READ_BLOCK
+ *       APR_WRITE_BLOCK
+ *       APR_FULL_NONBLOCK
+ * </pre>
+ * @param pool The pool to operate on.
+ * @remark By default, the returned file descriptors will be inherited
+ * by child processes created using apr_proc_create().  This can be
+ * changed using apr_file_inherit_unset().
+ */
+APR_DECLARE(apr_status_t) apr_file_namedpipe_open(apr_file_t **file,
+                                                  const char *fname,
+                                                  apr_int32_t flag,
+                                                  apr_int32_t blocking,
+                                                  apr_pool_t *pool);
+
+/**
  * Create a named pipe.
  * @param filename The filename of the named pipe
  * @param perm The permissions for the newly created pipe.
===================================================================
--- file_io/unix/pipe.c.orig	2012-12-18 13:19:53.000000000 -0800
+++ file_io/unix/pipe.c	2012-12-18 13:17:33.000000000 -0800
@@ -249,6 +249,70 @@
     return APR_SUCCESS;
 }
 
+APR_DECLARE(apr_status_t) apr_file_namedpipe_open(apr_file_t **file,
+                                                  const char *fname,
+                                                  apr_int32_t flag,
+                                                  apr_int32_t blocking,
+                                                  apr_pool_t *pool)
+{
+    apr_os_file_t fd;
+    int oflags = 0;
+    int oblock = 0;
+    struct_stat info;
+
+    if ((flag & APR_FOPEN_READ) && (flag & APR_FOPEN_WRITE)) {
+        oflags = O_RDWR;
+        oblock = (blocking != APR_FULL_NONBLOCK);
+    }
+    else if (flag & APR_FOPEN_READ) {
+        oflags = O_RDONLY;
+        oblock = (blocking == APR_FULL_BLOCK || blocking == APR_READ_BLOCK);
+    }
+    else if (flag & APR_FOPEN_WRITE) {
+        oflags = O_WRONLY;
+        oblock = (blocking == APR_FULL_BLOCK || blocking == APR_WRITE_BLOCK);
+    }
+    else {
+        return APR_EACCES;
+    }
+
+    if (!oblock) {
+        oflags |= O_NONBLOCK;
+    }
+
+    fd = open(fname, oflags);
+    if (fd < 0) {
+       return errno;
+    }
+
+    if (fstat(fd, &info) != 0) {
+        apr_status_t rv = errno;
+
+        close(fd);
+        return rv;
+    }
+#if defined(S_IFFIFO)
+    if ((info.st_mode & S_IFMT) != S_IFFIFO) {
+#elif defined(S_ISFIFO)
+    if (!S_ISFIFO(info.st_mode)) {
+#else
+    {
+#endif
+        close(fd);
+        return EBADF;
+    }
+
+    apr_os_pipe_put_ex(file, &fd, 1, pool);
+
+    if (blocking) {
+        pipeblock(*file);
+    } else {
+        pipenonblock(*file);
+    }
+
+    return APR_SUCCESS;
+}
+
 APR_DECLARE(apr_status_t) apr_file_namedpipe_create(const char *filename, 
                                                     apr_fileperms_t perm, apr_pool_t *pool)
 {
===================================================================

-- 
GPG Key ID: 088335A9
GPG Key Fingerprint: 86CD 3297 7493 75BC F820  6715 F54F E648 0883 35A9


Mime
View raw message