Hey,

For a few months I've been using the attached patch to mod_mono which does two things:

When there are mod_mono config directives in VirtualHost sections (at least in Apache2), the configurations end up stored in per-vhost data structures that can't see each other. As a result, each 'default'-alias mod-mono-server (for each vhost) launches its own mod-mono-server, but on the same Unix socket. So the first server launched, configured for just one vhost, is used for all of the vhosts.

To prevent these name clashes, I use the ServerName of a vhost as the default alias within a vhost.

The second change, which has debatable use, redirects the standard in/out of each forked mod-mono-server to a separate log file in /tmp so they can be viewed from the mod_mono control panel. (Since the main error_log is root-owned and mod_mono is running at lower privs (e.g. the 'apache' user), mod_mono didn't have access to read it.) That makes it possible to do Console.Errror.WriteLine debugging without needing root access to see the output. (I have yet to learn how to use the Tracing stuff of System.Web.)

What do people think of the second change?

Just as a reminder, you can turn on a mod_mono control panel with:
<Location /monoctrl/>
  SetHandler mono-ctrl
  (access restrictions here!)
</Location>
And then view it at: http://yourdomain.com/monoctrl/

--
- Joshua Tauberer

http://taubz.for.net

** Nothing Unreal Exists **


Index: src/mod_mono.c
===================================================================
--- src/mod_mono.c	(revision 50181)
+++ src/mod_mono.c	(working copy)
@@ -69,6 +69,7 @@
 	char *env_vars;
 	char status; /* One of the FORK_* in the enum above.
 		      * Don't care if run_xsp is "false" */
+	char is_default;
 	char is_virtual; /* is the server virtual? */
 } xsp_data;
 
@@ -84,12 +85,14 @@
 	int i;
 	xsp_data *xsp;
 
+	if (alias != NULL && !strcmp(alias, "default"))
+		alias = NULL;
+	
 	for (i = 0; i < config->nservers; i++) {
 		xsp = &config->servers [i];
-		if (alias == NULL && !strcmp (xsp->alias, "default"))
+		if (alias != NULL && !strcmp (alias, xsp->alias))
 			return i;
-
-		if (!strcmp (alias, xsp->alias))
+		else if (alias == NULL && xsp->is_default)
 			return i;
 	}
 
@@ -105,7 +108,7 @@
 	sconfig = ap_get_module_config (cmd->server->module_config, &mono_module);
 	config->alias = (char *) alias;
 	if (search_for_alias (alias, sconfig) == -1) {
-		char *err = apr_pstrcat (cmd->pool, "Server alias '", alias, ", not found.", NULL);
+		char *err = apr_pstrcat (cmd->pool, "Server alias '", alias, "', not found.", NULL);
 		return err;
 	}
 
@@ -113,7 +116,7 @@
 }
 
 static int
-add_xsp_server (apr_pool_t *pool, const char *alias, module_cfg *config, int is_virtual)
+add_xsp_server (apr_pool_t *pool, const char *alias, module_cfg *config, const char *vhostName)
 {
 	xsp_data *server;
 	xsp_data *servers;
@@ -121,11 +124,18 @@
 	int i;
 	char is_default;
 
+	is_default = (alias == NULL || !strcmp (alias, "default"));
+	
+	// The default alias within vhosts is the vhost's name, so that
+	// the unix socket file and log file don't clash with those
+	// for other vhosts.
+	if (is_default && vhostName != NULL)
+		alias = vhostName;
+	
 	i = search_for_alias (alias, config);
 	if (i >= 0)
 		return i;
 
-	is_default = (alias == NULL || !strcmp (alias, "default"));
 	server = apr_pcalloc (pool, sizeof (xsp_data));
 	server->alias = apr_pstrdup (pool, alias);
 	server->filename = NULL;
@@ -147,7 +157,8 @@
 	server->debug = "False";
 	server->env_vars = NULL;
 	server->status = FORK_NONE;
-	server->is_virtual = is_virtual;
+	server->is_virtual = (vhostName != NULL);
+	server->is_default = is_default;
 
 	nservers = config->nservers + 1;
 	servers = config->servers;
@@ -187,7 +198,7 @@
 
 	idx = search_for_alias (alias, config);
 	if (idx == -1)
-		idx = add_xsp_server (cmd->pool, alias, config, cmd->server->is_virtual);
+		idx = add_xsp_server (cmd->pool, alias, config, cmd->server->is_virtual ? cmd->server->server_hostname : NULL);
 
 	ptr = (char *) &config->servers [idx];
 	ptr += offset;
@@ -913,6 +924,42 @@
 #endif
 }
 
+static int
+open_server_log (xsp_data *config, int method) {
+	// Opens a log file for this mod-mono-server which
+	// has the same name as the Unix socket file + '.log'.
+	// The log file is truncated each time mod-mono-server
+	// is launched.
+	
+	apr_pool_t *pool;
+	apr_pool_create(&pool, NULL);
+
+	char *fn = config->filename;
+	if (fn == NULL)
+		fn = get_default_socket_name (pool, config->alias, SOCKET_FILE);
+	char *log_file = apr_pcalloc(pool, strlen(fn) + 4 + 1);
+	strcpy(log_file, fn);
+	strcat(log_file, ".log");
+	
+	int fd = -1;
+	
+	switch (method) {
+		case 0: // open for writing 
+			fd = open(log_file, O_WRONLY | O_CREAT | O_TRUNC | O_APPEND, S_IRUSR | S_IWUSR);
+			break;
+		case 1: // open for reading
+			fd = open(log_file, O_RDONLY);
+			break;
+		case 2: // delete log
+			unlink(log_file);
+			break;
+	}
+	
+	apr_pool_destroy(pool);
+	
+	return fd;
+}
+
 static void
 fork_mod_mono_server (apr_pool_t *pool, xsp_data *config)
 {
@@ -999,6 +1046,19 @@
 #endif
 	for (i = getdtablesize () - 1; i >= 3; i--)
 		close (i);
+		
+	// Redirect standard err/out to the mod-mono-server log file.
+	if (TRUE) {
+		int fd = open_server_log(config, 0);
+		if (fd == -1) {
+			ap_log_error (APLOG_MARK, APLOG_ERR, STATUS_AND_SERVER,
+				"Error open log file: %s", strerror (errno));
+		} else {
+			dup2(fd, 1);
+			dup2(fd, 2);
+			close(fd);
+		}
+	}
 
 	set_process_limits (max_cpu_time, max_memory);
 	tmp = getenv ("PATH");
@@ -1327,7 +1387,7 @@
 }
 
 static void
-start_xsp (module_cfg *config, int is_restart)
+start_xsp (module_cfg *config, int is_restart, char *alias)
 {
 	apr_socket_t *sock;
 	apr_status_t rv;
@@ -1348,6 +1408,9 @@
 
 		if (xsp->status != FORK_NONE)
 			continue;
+		
+		if (alias != NULL && strcmp(xsp->alias, alias))
+			continue;
 
 #ifdef APACHE13
 		sock = apr_pcalloc (pconf, sizeof (apr_socket_t));
@@ -1380,7 +1443,7 @@
 }
 
 static apr_status_t
-terminate_xsp (void *data)
+terminate_xsp2 (void *data, char *alias)
 {
 	server_rec *server;
 	module_cfg *config;
@@ -1398,6 +1461,9 @@
 		xsp = &config->servers [i];
 		if (xsp->run_xsp && !strcasecmp (xsp->run_xsp, "false"))
 			continue;
+		if (alias != NULL && strcmp(xsp->alias, alias))
+			continue;
+		
 #ifdef APACHE13
 		sock = apr_pcalloc (pconf, sizeof (apr_socket_t));
 #endif
@@ -1415,6 +1481,8 @@
 
 			remove (fn); /* Don't bother checking error */
 		}
+		
+		open_server_log(xsp, 2); // delete the log file
 
 		xsp->status = FORK_NONE;
 	}
@@ -1423,11 +1491,68 @@
 	return APR_SUCCESS;
 }
 
+static apr_status_t
+terminate_xsp (void *data)
+{
+	return terminate_xsp2(data, NULL);
+}
+
+static void
+control_panel_write_xsp_log (char *alias, module_cfg *config, request_rec *r)
+{
+	xsp_data *xsp;
+	int i;
+
+	for (i = 0; i < config->nservers; i++) {
+		xsp = &config->servers [i];
+		if (xsp->run_xsp && !strcasecmp (xsp->run_xsp, "false"))
+			continue;
+		if (alias != NULL && strcmp(xsp->alias, alias))
+			continue;
+			
+		int fd = open_server_log(xsp, 1);
+		if (fd == -1) {
+			request_send_response_string (r, "(Log file not present or could not be opened.)");
+			return;
+		}
+		
+		int max_output = 1024*100; // 100KB
+		
+		char buffer[2048];
+		int rlen;
+		
+		off_t lof = lseek(fd, 0, SEEK_END);
+		if (lof < max_output) {
+			lseek(fd, 0, SEEK_SET); // back to start of file
+		} else {
+			lseek(fd, lof-max_output, SEEK_SET);
+			// start on next newline
+			while ((rlen = read(fd, buffer, 1)))
+				if (buffer[0] == '\n' || buffer[0] == '\r')
+					break;
+		}
+		
+		// dump the rest of the file
+		while ((rlen = read(fd, buffer, sizeof(buffer)-1))) {
+			buffer[rlen] = 0;
+			request_send_response_string (r, buffer);
+		}
+		
+		close (fd);
+		return;
+	}
+	
+	request_send_response_string (r, "(No log available for this process.)");
+}
+
 static int
 mono_control_panel_handler (request_rec *r)
 {
 	module_cfg *config;
 	apr_uri_t *uri;
+	xsp_data *xsp;
+	int i;
+	char buffer[512];
 
 	if (strcmp (r->handler, "mono-ctrl"))
 		return DECLINED;
@@ -1445,14 +1570,33 @@
 	if (!uri->query || !strcmp (uri->query, "")) {
 		/* No query string -> Emit links for configuration commands. */
 		request_send_response_string (r, "<ul style=\"text-align: center;\">\n");
-		request_send_response_string (r, "<li><a href=\"?restart\">Restart mod-mono-server processes</a></li>\n");
+		request_send_response_string (r, "<li><a href=\"?restart\">Restart all mod-mono-server processes</a></li>\n");
+
+		for (i = 0; i < config->nservers; i++) {
+			xsp = &config->servers [i];
+			if (xsp->run_xsp && !strcasecmp (xsp->run_xsp, "false"))
+				continue;
+			sprintf(buffer, "<li>%s: <a href=\"?log=%s\">View Log</a> | <a href=\"?restart=%s\">Restart Server</a></li>\n", xsp->alias, xsp->alias, xsp->alias);
+			request_send_response_string(r, buffer);
+		}
+		
 		request_send_response_string (r, "</ul>\n");
 	} else {
 		if (uri->query && !strcmp (uri->query, "restart")) {
 			/* Restart the mod-mono-server processes */
-			terminate_xsp (r->server);
-			start_xsp (config, 1);
+			terminate_xsp2 (r->server, NULL);
+			start_xsp (config, 1, NULL);
 			request_send_response_string (r, "<div style=\"text-align: center;\">mod-mono-server processes restarted.</div><br>\n");
+		} else if (uri->query && !strncmp (uri->query, "restart=", 8)) {
+			/* Restart the mod-mono-server processes */
+			terminate_xsp2 (r->server, uri->query+8);  // +8 == .Substring(8)
+			start_xsp (config, 1, uri->query+8);
+			request_send_response_string (r, "<div style=\"text-align: center;\">mod-mono-server processes restarted.</div><br>\n");
+		} else if (uri->query && !strncmp (uri->query, "log=", 4)) {
+			/* View the log for this process. */
+			request_send_response_string (r, "<div style=\"text-align: left;\"><pre>");
+			control_panel_write_xsp_log(uri->query+4, config, r);
+			request_send_response_string (r, "</pre></div>\n");
 		} else {
 			/* Invalid command. */
 			request_send_response_string (r, "<div style=\"text-align: center;\">Invalid query string command.</div>\n");
@@ -1525,7 +1669,7 @@
 	DEBUG_PRINT (0, "Mono Child Init");
 	config = ap_get_module_config (s->module_config, &mono_module);
 
-	start_xsp (config, 0);
+	start_xsp (config, 0, NULL);
 }
 
 #ifdef APACHE13
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 50181)
+++ ChangeLog	(working copy)
@@ -1,3 +1,18 @@
+2005-09-17 Joshua Tauberer <[EMAIL PROTECTED]>
+
+	* src/mod_mono.c:
+	
+	  The default alias for xsp's within vhosts is the name of the
+	  vhost server, so that vhosts with default aliases don't all
+	  use the same Unix socket file name.
+	  
+	  The control panel is amended so that individual m-m-servers
+	  can be restarted.
+	  
+	  Standard out/error of forked mmservers are redirected to
+	  a log file that the control panel has read/write access to,
+	  and a View Log command is added to the control panel.
+
 2005-09-01 Gonzalo Paniagua Javier <[EMAIL PROTECTED]>
 
 	* src/mod_mono.[ch]: one single read for all the headers.
_______________________________________________
Mono-devel-list mailing list
Mono-devel-list@lists.ximian.com
http://lists.ximian.com/mailman/listinfo/mono-devel-list

Reply via email to