text:
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/un.h>
#include <cstring>
#include <unistd.h>
#include <errno.h>
#include <signal.h>
#include <pwd.h>

#include <set>
#include <vector>
#include <string>

#include <boost/thread.hpp>
#include <boost/shared_ptr.hpp>
#include "oxt/thread.hpp"
#include "oxt/system_calls.hpp"

#include "ScgiRequestParser.h"
#include "HttpStatusExtractor.h"

#include "StandardApplicationPool.h"
#include "ApplicationPoolStatusReporter.h"
#include "Application.h"
#include "PoolOptions.h"
#include "Exceptions.h"
#include "Utils.h"

using namespace boost;
using namespace oxt;
using namespace Passenger;

#define HELPER_SERVER_PASSWORD_SIZE     64

/**
 * Wrapper class around a file descriptor integer, for RAII behavior.
 *
 * A FileDescriptor object behaves just like an int, so that you can pass it to
 * system calls such as read(). It performs reference counting. When the last
 * copy of a FileDescriptor has been destroyed, the underlying file descriptor
 * will be automatically closed.
 */
class FileDescriptor {
private:
	struct SharedData {
		int fd;

		/**
		 * Constructor to assign this file descriptor's handle.
		 */
		SharedData(int fd) {
			this->fd = fd;
		}

		/**
		 * Attempts to close this file descriptor. When created on the stack,
		 * this destructor will automatically be invoked as a result of C++
		 * semantics when exiting the scope this object was created in. This
		 * ensures that stack created objects with destructors like these will
		 * de-allocate their resources upon leaving their corresponding scope.
		 * This pattern is also known Resource Acquisition Is Initialization (RAII).
		 *
		 * @throws SystemException File descriptor could not be closed.
		 */
		~SharedData() {
			if (syscalls::close(fd) == -1) {
				throw SystemException("Cannot close file descriptor", errno);
			}
		}
	};

	/* Shared pointer for reference counting on this file descriptor */
	shared_ptr<SharedData> data;

public:
	FileDescriptor() {
		// Do nothing.
	}

	/**
	 * Creates a new FileDescriptor instance with the given fd as a handle.
	 */
	FileDescriptor(int fd) {
		data = ptr(new SharedData(fd));
	}

	/**
	 * Overloads the integer cast operator so that it will return the file
	 * descriptor handle as an integer.
	 *
	 * @return This file descriptor's handle as an integer.
	 */
	operator int () const {
		return data->fd;
	}
};

struct ClientDisconnectedException { };

/**
 * A representation of a Client from the Server's point of view. This class
 * contains the methods used to communicate from a server to a connected
 * client, i.e. it is a client handler.
 * These Client instances will communicate concurrently with the server through
 * threads. Considering the overhead of these threads, i.e. setup and teardown
 * costs and the volatility of client requests, these client instances will be
 * pooled. It is for this reason that the State design pattern has been applied:
 * this class can be considered as being a skeleton implemention whose state
 * --e.g. the client file descriptor-- needs to be provided in order to function
 * properly.
 */
class Client {
private:
	/** The client thread stack size in bytes. */
	static const int CLIENT_THREAD_STACK_SIZE = 1024 * 128;

	/** The client number for this Client object, assigned by Server. */
	unsigned int number;

	/** The application pool to which this Client object belongs to. */
	StandardApplicationPoolPtr pool;

	/** This client's password. */
	string password;

	/** Whether privilege lowering should be used. */
	bool lowerPrivilege;

	/** The user that spawned processes should run as, if initial attempt
	 * at privilege lowering failed. */
	string lowestUser;

	/** The server socket file descriptor. */
	int serverSocket;

	/** This client's thread. */
	oxt::thread *thr;

	/**
	 * Attempts to accept a connection made by the client.
	 *
	 * @return The file descriptor corresponding to the accepted connection.
	 * @throws SystemException Could not accept new connection.
	 */
	FileDescriptor acceptConnection() {
		TRACE_POINT();
		struct sockaddr_un addr;
		socklen_t addrlen = sizeof(addr);
		int fd = syscalls::accept(serverSocket,
			(struct sockaddr *) &addr,
			&addrlen);
		if (fd == -1) {
			throw SystemException("Cannot accept new connection", errno);
		} else {
			return FileDescriptor(fd);
		}
	}

	/**
	 * Reads and checks the password of a client message channel identified by the given file descriptor.
	 * The HelperServer makes extensive use of Unix Sockets that would normally allow other processes to
	 * connect to it as well. In our case, we just want to limit this to Nginx and it is for this reason
	 * that we've secured communication channels between this server and its clients with passwords.
	 * This method indicates whether or not the password of this client channel matches the one known to
	 * the server.
	 *
	 * @param fd The file descriptor identifying the client message channel.
	 * @return True if the password of the client channel indicated by the given file descriptor
	 *   matches the password known to the server. False will be returned if either the
	 *   passwords don't match or EOF has been encountered.
	 */
	bool readAndCheckPassword(FileDescriptor &fd) {
		TRACE_POINT();
		MessageChannel channel(fd);
		char buf[HELPER_SERVER_PASSWORD_SIZE];

		if (channel.readRaw(buf, sizeof(buf))) {
			const char *password_data;

			password_data = const_cast<const string &>(password).c_str();
			return memcmp(password_data, buf, sizeof(buf)) == 0;
		} else {
			return false;
		}
	}

	/**
	 * Reads and parses the request headers from the given file descriptor with the given SCGI request parser
	 * and if succesful, assigns the remainder of the request (i.e. non SCGI header data) to the given
	 * requestBody.
	 *
	 * @param fd The file descriptor to read and parse from.
	 * @param parser The ScgiRequestParser to use for parsing the SCGI headers.
	 * @param requestBody The requestBody that was extracted as a result from parsing the SCGI headers.
	 * @return True if the request was succesfully read and parsed. False if an invalid SCGI header was
	 *   received by the parser or if the header information was invalid.
	 * @throws SystemException Request header could not be read.
	 */
	bool readAndParseRequestHeaders(FileDescriptor &fd, ScgiRequestParser &parser, string &requestBody) {
		TRACE_POINT();
		char buf[1024 * 16];
		ssize_t size;
		unsigned int accepted = 0;

		do {
			size = syscalls::read(fd, buf, sizeof(buf));
			if (size == -1) {
				throw SystemException("Cannot read request header", errno);
			} else if (size == 0) {
				break;
			} else {
				accepted = parser.feed(buf, size);
			}
		} while (parser.acceptingInput());

		if (parser.getState() != ScgiRequestParser::DONE) {
			P_ERROR("Invalid SCGI header received.");
			return false;
		} else if (!parser.hasHeader("DOCUMENT_ROOT")) {
			P_ERROR("DOCUMENT_ROOT header is missing.");
			return false;
		} else {
			requestBody.assign(buf + accepted, size - accepted);
			return true;
		}
	}

	/**
	 * Sends a request body to this client. The <tt>partialRequestBody</tt> will first be
	 * sent to the specified <tt>session</tt>, but if the specified <tt>contentLength</tt>
	 * is larger than the size of the <tt>partialRequestBody</tt>, then this method will
	 * attempt to read the remaining bytes from the specified <tt>clientFd</tt> and send it
	 * to the <tt>session</tt> as well until <tt>contentLength</tt> bytes have been sent in
	 * total.
	 *
	 * @param session The Ruby on Rails application instance.
	 * @param clientFd The client file descriptor to send the request body to.
	 * @param partialRequestBody The partial request body to send to this client.
	 * @param contentLength The content length of the request body in bytes.
	 * @throws SystemException Request body could not be read from the specified
	 *   <tt>clientFd</tt>.
	 */
	void sendRequestBody(Application::SessionPtr &session,
	                     FileDescriptor &clientFd,
	                     const string &partialRequestBody,
	                     unsigned long contentLength) {
		TRACE_POINT();
		char buf[1024 * 16];
		ssize_t size;
		size_t bytesToRead;
		unsigned long bytesForwarded = 0;

		if (partialRequestBody.size() > 0) {
			UPDATE_TRACE_POINT();
			session->sendBodyBlock(partialRequestBody.c_str(),
				partialRequestBody.size());
			bytesForwarded = partialRequestBody.size();
		}

		bool done = bytesForwarded == contentLength;
		while (!done) {
			UPDATE_TRACE_POINT();

			bytesToRead = contentLength - bytesForwarded;
			if (bytesToRead > sizeof(buf)) {
				bytesToRead = sizeof(buf);
			}
			size = syscalls::read(clientFd, buf, bytesToRead);

			if (size == 0) {
				done = true;
			} else if (size == -1) {
				throw SystemException("Cannot read request body", errno);
			} else {
				UPDATE_TRACE_POINT();
				session->sendBodyBlock(buf, size);
				bytesForwarded += size;
				done = bytesForwarded == contentLength;
			}
		}
	}

	/**
	 * Forwards an HTTP response from the given (Rails) <tt>session</tt> to the
	 * given <tt>clientFd</tt>.
	 *
	 * @param session The Ruby on Rails session to read the response from.
	 * @param clientFd The client file descriptor to write the response to.
	 * @throws SystemException Something went wrong while reading the response
	 *                         from the backend process or while writing to the
	 *                         response back to the web server.
	 * @throws ClientDisconnectedException The HTTP client closed the connection
	 *                                     before we were able to send back the
	 *                                     full response.
	 */
	void forwardResponse(Application::SessionPtr &session, FileDescriptor &clientFd) {
		TRACE_POINT();
		HttpStatusExtractor ex;
		int stream = session->getStream();
		int eof = false;
		MessageChannel output(clientFd);
		char buf[1024 * 32];
		ssize_t size;

		/* Read data from the backend process until we're able to
		 * extract the HTTP status line from it.
		 */
		while (!eof) {
			UPDATE_TRACE_POINT();
			size = syscalls::read(stream, buf, sizeof(buf));
			if (size == 0) {
				eof = true;
			} else if (size == -1) {
				throw SystemException("Cannot read response from backend process", errno);
			} else if (ex.feed(buf, size)) {
				/* We now have an HTTP status line. Send back
				 * a proper HTTP response, then exit this while
				 * loop and continue with forwarding the rest
				 * of the response data.
				 */
				UPDATE_TRACE_POINT();
				try {
					string statusLine("HTTP/1.1 ");
					statusLine.append(ex.getStatusLine());
					UPDATE_TRACE_POINT();
					output.writeRaw(statusLine.c_str(), statusLine.size());
					UPDATE_TRACE_POINT();
					output.writeRaw(ex.getBuffer().c_str(), ex.getBuffer().size());
					break;
				} catch (const SystemException &e) {
					if (e.code() == EPIPE) {
						throw ClientDisconnectedException();
					} else {
						throw;
					}
				}
			}
		}

		UPDATE_TRACE_POINT();
		while (!eof) {
			UPDATE_TRACE_POINT();
			size = syscalls::read(stream, buf, sizeof(buf));
			if (size == 0) {
				eof = true;
			} else if (size == -1) {
				throw SystemException("Cannot read response from backend process", errno);
			} else {
				UPDATE_TRACE_POINT();
				try {
					output.writeRaw(buf, size);
				} catch (const SystemException &e) {
					if (e.code() == EPIPE) {
						throw ClientDisconnectedException();
					} else {
						throw;
					}
				}
			}
		}
	}

	/**
	 * Handles a spawn related exception by writing an appropriate HTTP error response (500)
	 * for the given spawn exception <tt>e</ee> to given file descriptor <tt>fd</tt>'s message
	 * channel.
	 *
	 * @param fd The file descriptor identifying the message channel to write the given
	 *   spawn exception <tt>e</tt> to.
	 * @param e The spawn exception to be written to the given <tt>fd</tt>'s message
	 *   channel.
	 */
	void handleSpawnException(FileDescriptor &fd, const SpawnException &e) {
		MessageChannel channel(fd);
		channel.writeRaw("HTTP/1.1 500 Internal Server Error\x0D\x0A");
		channel.writeRaw("Status: 500 Internal Server Error\x0D\x0A");
		channel.writeRaw("Connection: close\x0D\x0A");
		channel.writeRaw("Content-Type: text/html; charset=utf-8\x0D\x0A");

		if (e.hasErrorPage()) {
			channel.writeRaw("Content-Length: " +
				toString(e.getErrorPage().size()) +
				"\x0D\x0A");
			channel.writeRaw("\x0D\x0A");
			channel.writeRaw(e.getErrorPage());
		} else {
			channel.writeRaw("Content-Length: " +
				toString(strlen(e.what())) + "\x0D\x0A");
			channel.writeRaw("\x0D\x0A");
			channel.writeRaw(e.what());
		}
	}

	/**
	 * Handles an SCGI request from a client whose identity is derived by the given <tt>clientFd</tt>.
	 *
	 * @param clientFd The file descriptor identifying the client to handle the request from.
	 */
	void handleRequest(FileDescriptor &clientFd) {
		TRACE_POINT();
		ScgiRequestParser parser;
		string partialRequestBody;
		unsigned long contentLength;

		if (!readAndCheckPassword(clientFd)) {
			P_ERROR("Client did not send a correct password.");
			return;
		}
		if (!readAndParseRequestHeaders(clientFd, parser, partialRequestBody)) {
			return;
		}

		try {
			PoolOptions options;
			if (parser.getHeader("SCRIPT_NAME").empty()) {
				options.appRoot = extractDirName(parser.getHeader("DOCUMENT_ROOT"));
			} else {
				options.appRoot = extractDirName(resolveSymlink(parser.getHeader("DOCUMENT_ROOT")));
				options.baseURI = parser.getHeader("SCRIPT_NAME");
			}
			options.useGlobalQueue = parser.getHeader("PASSENGER_USE_GLOBAL_QUEUE") == "true";
			options.environment    = parser.getHeader("PASSENGER_ENVIRONMENT");
			options.spawnMethod    = parser.getHeader("PASSENGER_SPAWN_METHOD");
			options.lowerPrivilege = lowerPrivilege;
			options.lowestUser     = lowestUser;
			options.appType        = parser.getHeader("PASSENGER_APP_TYPE");
			options.frameworkSpawnerTimeout = atol(parser.getHeader("PASSENGER_FRAMEWORK_SPAWNER_IDLE_TIME"));
			options.appSpawnerTimeout       = atol(parser.getHeader("PASSENGER_APP_SPAWNER_IDLE_TIME"));

			try {
				Application::SessionPtr session(pool->get(options));

				UPDATE_TRACE_POINT();
				session->sendHeaders(parser.getHeaderData().c_str(),
					parser.getHeaderData().size());

				contentLength = atol(
					parser.getHeader("CONTENT_LENGTH").c_str());
				sendRequestBody(session,
					clientFd,
					partialRequestBody,
					contentLength);

				session->shutdownWriter();
				forwardResponse(session, clientFd);
			} catch (const SpawnException &e) {
				handleSpawnException(clientFd, e);
			} catch (const ClientDisconnectedException &) {
				P_WARN("Couldn't forward the HTTP response back to the HTTP client: "
					"It seems the user clicked on the 'Stop' button in his "
					"browser.");
			}
		} catch (const boost::thread_interrupted &) {
			throw;
		} catch (const tracable_exception &e) {
			P_ERROR("Uncaught exception in PassengerServer client thread:\n"
				<< "   exception: " << e.what() << "\n"
				<< "   backtrace:\n" << e.backtrace());
		} catch (const exception &e) {
			P_ERROR("Uncaught exception in PassengerServer client thread:\n"
				<< "   exception: " << e.what() << "\n"
				<< "   backtrace: not available");
		} catch (...) {
			P_ERROR("Uncaught unknown exception in PassengerServer client thread.");
		}
	}

	/**
	 * This client's main thread, responsible for accepting connections made by a client
	 * to the server and to handle its request.
	 *
	 * @see acceptConnection(void)
	 * @see handleRequest(FileDescriptor)
	 */
	void threadMain() {
		TRACE_POINT();
		try {
			while (true) {
				UPDATE_TRACE_POINT();
				FileDescriptor fd(acceptConnection());
				handleRequest(fd);
			}
		} catch (const boost::thread_interrupted &) {
			P_TRACE(2, "Client thread " << this << " interrupted.");
		} catch (const tracable_exception &e) {
			P_ERROR("Uncaught exception in PassengerServer client thread:\n"
				<< "   exception: " << e.what() << "\n"
				<< "   backtrace:\n" << e.backtrace());
			abort();
		} catch (const exception &e) {
			P_ERROR("Uncaught exception in PassengerServer client thread:\n"
				<< "   exception: " << e.what() << "\n"
				<< "   backtrace: not available");
			abort();
		} catch (...) {
			P_ERROR("Uncaught unknown exception in PassengerServer client thread.");
			throw;
		}
	}

public:
	/**
	 * Constructs a client handler for the server with the given arguments and runs
	 * it in its own thread.
	 *
	 * @param number The id assigned by the server to identify this client by.
	 * @param pool The application pool where this client belongs to.
	 * @param password The password that is required to connect to this client handler.
	 *   This value is determined and assigned by the server.
	 * @param lowerPrivilege Whether privilege lowering should be used.
	 * @param lowestUser The user that spawned processes should run as, if
	 *   initial attempt at privilege lowering failed.
	 * @param serverSocket The server socket to accept this clients connection from.
	 */
	Client(unsigned int number, StandardApplicationPoolPtr &pool,
	       const string &password, bool lowerPrivilege,
	       const string &lowestUser, int serverSocket) {
		this->number = number;
		this->pool = pool;
		this->password = password;
		this->lowerPrivilege = lowerPrivilege;
		this->lowestUser = lowestUser;
		this->serverSocket = serverSocket;
		thr = new oxt::thread(
			bind(&Client::threadMain, this),
			"Client thread " + toString(number),
			CLIENT_THREAD_STACK_SIZE
		);
	}

	/**
	 * Destroys this client and its thread.
	 */
	~Client() {
		TRACE_POINT();
		this_thread::disable_syscall_interruption dsi;
		this_thread::disable_interruption di;

		thr->interrupt_and_join();
		delete thr;
	}
};

typedef shared_ptr<Client> ClientPtr;

/**
 * A representation of the Server responsible for handling Client instances.
 *
 * @see Client
 */
class Server {
private:
	string password;
	int adminPipe;
	int serverSocket;
	bool userSwitching;
	string defaultUser;
	unsigned int numberOfThreads;
	set<ClientPtr> clients;
	StandardApplicationPoolPtr pool;
	shared_ptr<ApplicationPoolStatusReporter> reporter;

	/**
	 * Starts listening for client connections from this server's <tt>serverSocket</tt>.
	 * This server will first attempt to create an unconnected Unix socket on which it will
	 * attempt to bind on. Once it is bound, it will start listening for incoming client
	 * activity.
	 *
	 * @throws SystemException Something went wrong while trying to create and bind to the Unix socket.
	 * @throws RuntimeException Something went wrong.
	 */
	void startListening() {
		this_thread::disable_syscall_interruption dsi;
		string socketName = getPassengerTempDir() + "/master/helper_server.sock";
		serverSocket = createUnixServer(socketName.c_str());

		int ret;
		do {
			ret = chmod(socketName.c_str(), S_ISVTX |
				S_IRUSR | S_IWUSR | S_IXUSR |
				S_IRGRP | S_IWGRP | S_IXGRP |
				S_IROTH | S_IWOTH | S_IXOTH);
		} while (ret == -1 && errno == EINTR);
	}

	/**
	 * Starts the client handler threads that are responsible for handling the communication
	 * between the client and this Server.
	 *
	 * @see Client
	 */
	void startClientHandlerThreads() {
		for (unsigned int i = 0; i < numberOfThreads; i++) {
			ClientPtr client(new Client(i + 1, pool, password,
				userSwitching, defaultUser, serverSocket));
			clients.insert(client);
		}
	}

	/**
	 * Lowers this process's privilege to that of username.
	 */
	void lowerPrivilege(const string &username) {
		struct passwd *entry;

		entry = getpwnam(username.c_str());
		if (entry != NULL) {
			if (initgroups(username.c_str(), entry->pw_gid) != 0) {
				int e = errno;
				P_WARN("WARNING: Unable to lower Passenger HelperServer's "
					"privilege to that of user '" << username <<
					"': cannot set supplementary groups for this "
					"user: " << strerror(e) << " (" << e << ")");
			}
			if (setgid(entry->pw_gid) != 0) {
				int e = errno;
				P_WARN("WARNING: Unable to lower Passenger HelperServer's "
					"privilege to that of user '" << username <<
					"': cannot set group ID: " << strerror(e) <<
					" (" << e << ")");
			}
			if (setuid(entry->pw_uid) != 0) {
				int e = errno;
				P_WARN("WARNING: Unable to lower Passenger HelperServer's "
					"privilege to that of user '" << username <<
					"': cannot set user ID: " << strerror(e) <<
					" (" << e << ")");
			}
		} else {
			P_WARN("WARNING: Unable to lower Passenger HelperServer's "
				"privilege to that of user '" << username <<
				"': user does not exist.");
		}
	}

public:
	/**
	 * Creates a server instance based on the given parameters, which starts to listen
	 * for clients.
	 *
	 * @param password The password this server uses for its clients.
	 * @param rootDir The Passenger root folder.
	 * @param ruby The filename of the Ruby interpreter to use.
	 * @param adminPipe The pipe that is used to receive this Server's password and to see if Nginx
	 *   has exited.
	 * @param feedbackPipe The feedback pipe, used for telling the web server that we're done
	 *   initializing.
	 * @param maxPoolSize The maximum number of simultaneously alive application instances.
	 * @param maxInstancesPerApp The maximum number of simultaneously alive Rails instances that
	 *   a single Rails application may occupy.
	 * @param poolIdleTime The maximum number of seconds that an application may be idle before
	 *   it gets terminated.
	 * @param userSwitching Whether user switching should be used.
	 * @param defaultUser If user switching is turned on, then this is the
	 *   username that a process should lower its privilege to if the
	 *   initial attempt at user switching fails. If user switching is off,
	 *   then this is the username that HelperServer and all spawned
	 *   processes should run as.
	 * @param workerUid The UID of the web server's worker processes. Used for determining
	 *   the optimal permissions for some temp files.
	* @param workerGid The GID of the web server's worker processes. Used for determining
	 *   the optimal permissions for some temp files.
	 */
	Server(const string &password, const string &rootDir, const string &ruby,
	       int adminPipe, int feedbackPipe, unsigned int maxPoolSize,
	       unsigned int maxInstancesPerApp, unsigned int poolIdleTime,
	       bool userSwitching, const string &defaultUser, uid_t workerUid,
	       gid_t workerGid) {
		this->password      = password;
		this->adminPipe     = adminPipe;
		this->userSwitching = userSwitching;
		this->defaultUser   = defaultUser;
		numberOfThreads     = maxPoolSize * 4;

		removeDirTree(getPassengerTempDir());
		createPassengerTempDir(getSystemTempDir(), userSwitching, defaultUser,
			workerUid, workerGid);
		startListening();

		if (!userSwitching && geteuid() == 0) {
			lowerPrivilege(defaultUser);
		}

		pool = ptr(new StandardApplicationPool(
			rootDir + "/bin/passenger-spawn-server",
			"", ruby
		));
		pool->setMax(maxPoolSize);
		pool->setMaxPerApp(maxInstancesPerApp);
		pool->setMaxIdleTime(poolIdleTime);

		reporter = ptr(new ApplicationPoolStatusReporter(pool, userSwitching,
				S_IRUSR | S_IWUSR));

		// Tell the web server that we're done initializing.
		syscalls::close(feedbackPipe);
	}

	~Server() {
		TRACE_POINT();
		this_thread::disable_syscall_interruption dsi;
		this_thread::disable_interruption di;

		P_DEBUG("Shutting down helper server...");
		clients.clear();
		P_TRACE(2, "All threads have been shut down.");
		syscalls::close(serverSocket);
		syscalls::close(adminPipe);
	}

	/**
	 * Starts this server by starting the client handlers threads.
	 *
	 * @see startCientHandlerThreads
	 */
	void start() {
		TRACE_POINT();
		char buf;

		startClientHandlerThreads();

		try {
			// Wait until the web server has exited.
			syscalls::read(adminPipe, &buf, 1);
		} catch (const boost::thread_interrupted &) {
			// Do nothing.
		}
	}
};

/**
 * Ignores the SIGPIPE signal that in general is raised when a computer program attempts
 * to write to a pipe without a processes connected to the other end. This is used to
 * prevent Nginx from getting killed by the default signal handler when it attempts to
 * write the server password to the HelperServer in the situation that the HelperServer
 * failed to start.
 */
static void
ignoreSigpipe() {
	struct sigaction action;
	action.sa_handler = SIG_IGN;
	action.sa_flags   = 0;
	sigemptyset(&action.sa_mask);
	sigaction(SIGPIPE, &action, NULL);
}

/**
 * Extracts and returns the password from the given <tt>adminPipe</tt>. This password is
 * used to determine which processes may connect with this server's Unix socket, as unix
 * sockets would normally allow any process to connect to it. In this case, we strictly
 * want Nginx to be able to connect to it, and it is for this reason that we maintain a
 * password system.
 *
 * @param adminPipe The pipe used to read the password for this server from.
 * @return The password for this server.
 */
static string
receivePassword(int adminPipe) {
	TRACE_POINT();
	MessageChannel channel(adminPipe);
	char buf[HELPER_SERVER_PASSWORD_SIZE];

	if (!channel.readRaw(buf, HELPER_SERVER_PASSWORD_SIZE)) {
		throw IOException("Could not read password from the admin pipe.");
	}
	return string(buf, HELPER_SERVER_PASSWORD_SIZE);
}

/**
 * Initializes and starts the helper server that is responsible for handling communication
 * between Nginx and the backend Rails processes.
 *
 * @see Server
 * @see Client
 */
int
main(int argc, char *argv[]) {
	TRACE_POINT();
	try {
		setup_syscall_interruption_support();
		ignoreSigpipe();

		string password;
		string rootDir  = argv[1];
		string ruby      = argv[2];
		int adminPipe    = atoi(argv[3]);
		int feedbackPipe = atoi(argv[4]);
		int logLevel     = atoi(argv[5]);
		int maxPoolSize  = atoi(argv[6]);
		int maxInstancesPerApp = atoi(argv[7]);
		int poolIdleTime       = atoi(argv[8]);
		bool userSwitching = strcmp(argv[9], "1") == 0;
		string defaultUser = argv[10];
		uid_t workerUid    = (uid_t) atoll(argv[11]);
		gid_t workerGid    = (gid_t) atoll(argv[12]);
		string passengerTempDir = argv[13];

		setLogLevel(logLevel);
		P_DEBUG("Passenger helper server started on PID " << getpid());

		setPassengerTempDir(passengerTempDir);

		password = receivePassword(adminPipe);
		P_TRACE(2, "Password received.");

		Server(password, rootDir, ruby, adminPipe, feedbackPipe, maxPoolSize,
			maxInstancesPerApp, poolIdleTime, userSwitching,
			defaultUser, workerUid, workerGid).start();
	} catch (const tracable_exception &e) {
		P_ERROR(e.what() << "\n" << e.backtrace());
		return 1;
	} catch (const exception &e) {
		P_ERROR(e.what());
		return 1;
	} catch (...) {
		P_ERROR("Unknown exception thrown in main thread.");
		throw;
	}

	P_TRACE(2, "Helper server exited.");
	return 0;
}


text:
What are the white dots on my nails?
by Jason Nell
Personal Hygiene Image Gallery A condition called leukonychia can cause white spots on fingernails. See more personal hygiene pictures.
© iStockphoto.com/Linda Steward
You finally finished repainting those end tables for the guest room. As you're washing up, you notice something on your fingernail. You try to scrub it off and realize the little white dots are not paint; they're actually part of your nail.
You show the spots to your roommate and he says it could mean you have a calcium deficiency. Or wait, is it zinc? It's definitely some sort of nutritional deficit, of that he's certain. But you start to wonder if he's right because just last month, he told you that washing your face in egg whites will decrease the size of your pores. However, when you mentioned that to your dermatologist, she said that nothing can actually shrink your pores. So what are these white spots and how'd you get them?
One of the most common causes for these little white spots, which can show up on both fingernails and toenails, is a condition called leukonychia [source: Tuzun and Karakus]. Although the name sounds pretty serious, the condition typically isn't. And while many people think they're caused by a calcium or zinc deficiency, that's generally not the case [sources: Sound Medicine, Weil].
In reality, these spots most often develop as a result of mild to moderate trauma to your nail. If you can't think of anything that would have injured your nail, consider the fact that nails grow very slowly, so the injury may have occurred weeks before the spots ever appeared [source: WebMD]. Another possibility is that the spots could be a sign of a mild infection or allergy, or a side effect of certain medications [source: Weil].
Whatever the source of the injury, these spots typically do not require any treatment and should go away as your nail grows out. And they should not return unless you suffer another nail trauma [source: Weil]. However, this generally applies when only a single or a few nails are affected. If all of your nails are showing white spots or streaks, the leukonychia could be related to another more serious condition such as anemia, cardiac disease, cirrhosis, diabetes or kidney disease [source: Bryant]. Overall, it's good practice to pay attention to changes and abnormalities in your fingernails and to consult your doctor if you're concerned.
What you've just read is just the tip of the discussion when it comes to nail disorders. For more information, visit the links on the next page.
Top 5 Things Your Nails Say About Your Health
How Manicures Work
How Pedicures Work
Top 5 Ways to Prevent Nail Biting
Top 5 Treatments for Brittle Nails
American Academy of Dermatology (AAD). "Nail Fungus & Nail Health."
(Accessed 10/11/09)http://www.aad.org/public/publications/pamphlets/common_nail.html
Bryant, Rebecca. "Cures for some nail disorders more troublesome than others." Dermatology Times. August 2001. Accessed online via MasterFILE Premier, EBSCOhost (Accessed 11/10/09).
MedlinePlus. "Nail Abnormalities." (Accessed 10/19/09) http://www.nlm.nih.gov/medlineplus/ency/article/003247.htm
Rauh, Sherry. "Healthy Fingernails: Clues about your health." WebMD.(Accessed 10/11/09)http://www.webmd.com/skin-problems-and-treatments/features/healthy-fingernails-clues-about-health
Sound Medicine. "Medical Myth: White Spots on Fingernails." Indiana University.(Accessed 10/11/09)http://soundmedicine.iu.edu/segment/204/redirect?seg=204
Tuzun, Yalcin and Ozge Karakus. "Leukonychia." Journal of the Turkish Academy of Dermatology. (Accessed 10/11/09)http://74.125.95.132/search?q=cache:Q1HYU0eXd-kJ:www.jtad.org/2009/1/jtad93101r.pdf+Leukonychia&cd=12&hl=en&ct=clnk&gl=us&client=firefox-a
Weil, Andrew. "Worried about White Spots on Fingernails: Q & A." DrWeil.com(Accessed 10/11/09)http://www.drweil.com/drw/u/QAA350576/white-spots-on-fingernails.html
WebMD "Nail Problems and Injuries." (Accessed 10/11/09)http://www.webmd.com/skin-problems-and-treatments/tc/nail-problems-and-injuries-topic-overview
Top 10 Things Your Nails Say About Your Health
At a Glance: White Dots on Your Nails
How can nails be signals of systemic disease?
How to Treat Damaged Cuticles
How often should I cut my nails?
Will getting a pedicure help you go into labor?

redpajama_set_name: RedPajamaCommonCrawl


Spak GustavLindgren jasmin. nativepinay123. AvaBurton. SpaQueen.
GinaLuvKinkyMafeStacyMaelBustyPenellope .BestCoupleFckXPrincesaBrownKathySandersNinaSquirts .NinaSquirtsCrazyBigCockVSTsDulceLoveeSANDRAQQQ .angilirianoSweetJewellEffyAndMariettaErumiLin .jhefxxxSeXyCoUpLe696969LeoStCruzOnlyPvt .B1GjuicyMUSHRO0MDaoTouchSweetElten4UCrazyBigCockVSTs .BustyPenellopeTSDONNADOMINAxxGorgeusPRiNCESSxverysexyme .TightGoddessSweetJewellnativepinay123SweetElten4U .naughtyprincesssPrincesaBrownRyaMadison25MirabellCute .EBONNYXCARLETTaxel891SofiaXLemusDulceLovee .SweetJewellKosenWannaPlayCrazyBigCockVSTsHettiLove .
LeoStCruzLuxuryBlondie4Unativepinay123SANDRAQQQ .BustyPenellopeMarilynHotGirlangilirianoSweetJewell .SexyAngelaLoveLolaBigSquirtMSTRESSCUMfeederKathySanders .Sweetie964MissyAnnyBIGcoks10IToniaDelight .LuxuryBlondie4UTightGoddessBustyPenellopeErumiLin .MayaLunaMirabellCuteSWEETBLACKTSMarilynHotGirl .LuxuryBlondie4UEffyAndMariettagianni096yyLolaBigSquirt .CrazyBigCockVSTsaxel891lissapatrickexcentrique .1FlirtMadammladynatasha1976KosenWannaPlayAngelgirl20 .salma4uSWEETBLACKTSLeoStCruzNinaSquirts .TightGoddessParisFox4uStacyMaelDaoTouch .


This coffee maker is good for work. I have it in an office I share with two coworkers and it's enough for just us. The price is right if you are looking for somethung cheap without bells and whistles. We use paper filters so it's easier to clean. It doesn't come with a mesh filter like more expensive pots do but you can buy one. It's easy to clean and small enough to store when not in use. It might be good for a dorm or a first apartment. There are many reasons I wouldn't buy this for home use now. the design isn't sleek. I prefer the square look to coffe makers; however, this does usually mean it takes up more space. Also, it doesn't have a timer. If you want to make a certain amount of coffee you need to measure it for yourself. This is also not good for so,done entertaining as it does not make enough coffee for a party. I will say it has held up and its very easy to figure out how to use it. I have cleaned it by running water and vinegar through it and flushing it out a few times.
I love Mr Coffee products, they do what they are supposed to do and last a long time. This is my second Mr Coffee and the 4 cup size is nice. I like the reusable filter basket that comes with it, no more messy paper filters. Easy to use, easy to clean and the coffee always tastes good.
I purchased this coffee maker a few weeks ago and am quite satisfied with it. I opted for this model rather than the programmable because I decided I'd end up forgetting to prep it the night before and that making coffee in the morning is a relaxing part of our normal routine. The main reason for this purchase was to have a small amount of coffee on hand that I could drink throughout the morning/afternoon, and only have to make it once, compared to our other coffee machine with the disposable cups. (We were using a plastic reusable filter cup for it and it was very tedious to clean each time.) With this little machine you get 5 cups of coffee if you fill the reservoir up to the max line (you can't overfill it, there's a drain hole). They say 4 cups because it's 5 cups all the way to the top of the carafe. It pours easily without dripping and is small enough to easily lift when full. Cleaning the pot is a breeze and the footprint on the whole piece is nice and small at about 9 1/2" tall, 5 1/2" wide and about 7" deep with the handle sticking out. I'm not a big coffee drinker so the amount of coffee is perfect. I also pour it into a pitcher to make iced coffee and store that in the fridge. The best tip I can give you is that you can use paper filters in this if you prefer them over the reusable filter. An off-brand 10-12 cup filter (flat bottom, not cone) fits just fine and is easier to find than the smaller sizes. Now, a few negatives. I can't leave the coffee warming for more than 3 hours or so as it gets a burnt, off-taste. At least it did for me with a dark French roast. The plastic hinged lid on the top of the machine is difficult to close and I usually struggle with it for a few seconds before it snaps down. Not the end of the world, just a minor annoyance. And, it takes a long time to make a full pot of coffee, but, you can remove the carafe to fill your cup before it finishes. Nice little coffee maker all in all; does what it says it does and I am satisfied.
The Mr. Coffee 5-Cup Coffee Maker TF6 is a good coffee maker.
The Mr. Coffee 5-Cup Coffee Maker TF6 is a reasonably priced good-quality coffee maker. I also purchased mine at Wal Mart. I had intentions of purchasing a replacement decanter, but there were none in the size I wanted so I ended up purchasing this coffee maker. My previous coffee makers have been Mr. Coffee brand which have provided many years of service. This coffee maker does come with a permanent filter which I occasionally use. It gets messy when disposing of the used coffee grounds. I end up using the disposable paper filters sometimes so I can just dump the used filter in the trash. This coffee maker is the perfect size for me since I am only making the coffee for me. I can drink the whole pot by myself! Any coffee maker bigger than this size seems to be a waste. The newer single cup coffee makers are too small and more expensive, and the coffee for those coffee makers are too expensive.
I got this little Mr. Coffee unit at Wally World as a replacement for a similar one I'd had for years. I like this one slightly better. Well, so far, anyway. The jury's still out until this one lasts for years, too! What I like better is that this one has just one lid you flip up to get it set up. Pour the water in one place, put the coffee in the other, flip the lid down, turn it on, and it goes to work. It comes with one of those micro-filter baskets that makes the paper filters unnecessary, although they tell you it's also the right size for a small paper filter too, if you want to go that way. Why anybody would opt for fooling around with paper filters when you don't have to is beyond me, but, hey, to each his own, right? This thing is like all the rest of them -- when they say "cups" they mean teeny-weeny cups. So, for those of us who live in the real world, "4 cups" means "2 cups". They say you can do "5 cups", so I guess that means "2 1/2 cups" in the real world. Who defines this stuff, anyway, a bunch of little old ladies? So, anyway, if this thing will just keep doing what it does every morning for the next five years or so, it will rate as well as that Braun unit I just threw away. That one was made in Germany, this one is made in -- oh, you guessed it? -- China.


text:
David J Howe and Sam Stone at the SFX Weekender
By sfx 19 September 2011
Author and owner of Telos Publishing and award-winning horror novelist will join the literary line-up at our event in February 2012
Rapidly becoming a phenomenal occasion for fiction fans, the annual SFX Weekender has attracted many authors and publishers in its first two years. Readers will enjoy the third SFX Weekender festival (taking place 2-5 February) just as much by the looks of thing, with a great line-up of writers emerging and more yet to announce.
Today we're very pleased to confirm that David J Howe, owner of Telos Publishing and author of over 30 books about Doctor Who will be joining us there, as will award-winning horror novelist Sam Stone . She's the author of four published novels - the fourth was recently launched at the Asylum Steampunk event in Lincoln - and a short story collection, with a fifth novel on the way.
Sam Stone (left, above) began writing aged 11 after reading her first adult fiction book, The Collector by John Fowles. "I'd never read anything like it. It was terrifying – but so exciting … that's when I realised I liked to be scared," she admits. Sam's writing has appeared in nine anthologies for poetry and prose. Her first novel won the Silver Award for Best Horror Novel in ForeWord Magazine's book of the year awards in 2007. In September 2008 the novel was re-edited and republished by The House of Murky Depths as Killing Kiss. The sequels, Futile Flame and Demon Dance went on to become finalists in the same awards for 2009/2010.
David J Howe (right, above) has been involved with Doctor Who research and writing for over 30 years. He has been consultant to a large number of publishers and manufacturers for their Who lines, and is author or co-author of over 30 factual titles associated with the show. He also has one of the largest collections of Doctor Who merchandise in the world and is a journalist contributing articles and reviews to a wide variety of magazines. He edited the bi-monthly newsletter of the British Fantasy Society in the 1990s - he is currently Chair of the BFS, and edited their 40th anniversary anthology, Full Fathom Forty , published this month. In addition he is Editorial Director of Telos Publishing , a UK based independent press specialising in horror and science fiction novellas, crime novels, and guides to a variety of film and TV shows.
These two authors are in good company: the Weekender already boasts a line up that includes Sylvester McCoy, Eve Myles, Brian Blessed and a small army of writers and comic creators including the likes of Peter F Hamilton and Robert Rankin. It takes place in Prestatyn, north Wales, on Friday 3 February and Saturday 4 February 2012, with our pre-party on Thursday 2 February for the early birds. Checkout is the morning of Sunday 5 February. VIP tickets are already going fast, but there are many other options available. Make sure you get yours by calling 08700 11 00 34, or head to www.sfxweekender.com/tickets for more information.
The best Xbox One headsets


text:
Site Name: Rock_Lp
Location: Loves Park (Mildred Rd), IL
Reporting: False, Located: True
Current AQI: None
Loves Park (Mildred Rd) IL, US: 42.335, -89.0381
Oct. 26, 2020, noon N/A N/A N/A N/A N/A N/A 21.0 ppb (20) N/A N/A N/A 20.0
Oct. 26, 2020, 11 a.m. N/A N/A N/A N/A N/A N/A 21.0 ppb (20) N/A N/A N/A 20.0
Oct. 26, 2020, 9 a.m. N/A N/A N/A N/A N/A N/A 23.0 ppb (22) N/A N/A N/A 22.0
Oct. 26, 2020, midnight N/A N/A N/A N/A N/A N/A 23.0 ppb (22) N/A N/A N/A 22.0
Oct. 25, 2020, 11 p.m. N/A N/A N/A N/A N/A N/A 23.0 ppb (22) N/A N/A N/A 22.0
Oct. 25, 2020, 9 p.m. N/A N/A N/A N/A N/A N/A 24.0 ppb (23) N/A N/A N/A 23.0
Oct. 24, 2020, 10 a.m. N/A N/A N/A N/A N/A N/A 8.0 ppb (8) N/A N/A N/A 8.0
Oct. 24, 2020, 7 a.m. N/A N/A N/A N/A N/A N/A 9.0 ppb (9) N/A N/A N/A 9.0
Oct. 23, 2020, midnight N/A N/A N/A N/A N/A N/A 1.0 ppb (1) N/A N/A N/A 1.0
Oct. 22, 2020, 11 p.m. N/A N/A N/A N/A N/A N/A 1.0 ppb (1) N/A N/A N/A 1.0
Oct. 22, 2020, 9 p.m. N/A N/A N/A N/A N/A N/A 5.0 ppb (5) N/A N/A N/A 5.0
Oct. 20, 2020, noon N/A N/A N/A N/A N/A N/A 7.0 ppb (7) N/A N/A N/A 7.0
Previous Page 2 of 96 Next


Arch Enterprises provides platinum recovery services for industries throughout the United States. Platinum refining can be a very difficult and complicated procedure as platinum is a difficult precious metal to recover. Our highly-skilled, on-premise metallurgy team has many years of experience in recycling platinum and can ensure you the best return.
Plus, since we are not a middleman or consolidator, but actually do the platinum refining at our facilities, we can further assure you the best return based on the weight of the platinum refined from your material. We offer fast payment terms and all of the platinum we refine is recycled back to industrial sources.
Platinum recycling helps promote and protect the future use of a valuable natural resource. We are in compliance with all local, state, and federal environmental regulations and take full responsibility for any material we receive.
Platinum refining terms are customized based on the type and quantity of the platinum scrap you have and the service that you need. We have the capabilities to individually process large and small quantities. We can accept one-time shipments and large on-going quantities from industrial sources and work with both companies and individuals. We look forward to becoming your platinum refiner.


Samsung Galaxy devices are always good; most of them have unique best features and specifications. Samsung does not stopped its production to just smartphone and other handheld devices. It shows its peculiarity in other accessories also.
Now, it recently revealed the Samsung Mobile Beam Projector which is compatible with most of the Galaxy devices from Samsung and these include the Galaxy Smartphones, Galaxy Tabs, PCs and Galaxy Players.
The Projector looks just like a mobile phone, but it is smaller in size when compared with standard Galaxy S III. But there is no difference in design as it looks like a mobile phone, with one of the sides having the projector lens.
The only requirement of the device is that it should have the HDMI port and compatibility, and as soon as it is connected to the device, the detection is done automatically.
One sad thing about this Mobile Beam Projector is; only the Korean people would be able to buy it and take the full advantage of it. As of now, there is no information whether the international buyers would be able to purchase it.
The Mobile Beam Projector would have the 1650 mAh battery, and this is quite enough to project the screen for around 2 hours, when the brightness levels are around 20 lumens, and the content that is displayed is of nHd resolution with 640 x 360 pixels.
Its dimension is 116mm x 60.4mm x 12.2mm and there are sockets for the HDMI in and out, and a 5 point charging socket all on one side, while other side has the lens of the projector. A small speaker is also present along with a focus control button and status indicator light.
The projecting lens of the Beam Projector lies in the side panel, and the other side has got the power key along with the various sockets, and the charger point. The simple and slim projector connect to the smart devices like the smartphones and tablet devices and even the PCs, and are recognized easily and automatically when connected.


text:
package org.apache.skywalking.oap.server.analyzer.provider.trace.parser;

/**
 * Reserved keys of the span. The backend analysis the metrics according the existed tags.
 */
public class SpanTags {
    public static final String HTTP_RESPONSE_STATUS_CODE = "http.status_code";
    /**
     * Deprecated. The old status_code tag, in order to be compatible with the old version of agent.
     * It should be replaced by {@link #HTTP_RESPONSE_STATUS_CODE} or using
     * {@link #RPC_RESPONSE_STATUS_CODE} if status code is related to a rpc call.
     */
    @Deprecated
    public static final String STATUS_CODE = "status_code";

    public static final String RPC_RESPONSE_STATUS_CODE = "rpc.status_code";

    public static final String DB_STATEMENT = "db.statement";

    public static final String DB_TYPE = "db.type";

    public static final String CACHE_TYPE = "cache.type";

    public static final String CACHE_OP = "cache.op";

    public static final String CACHE_CMD = "cache.cmd";

    public static final String CACHE_KEY = "cache.key";

    public static final String MQ_QUEUE = "mq.queue";

    public static final String MQ_TOPIC = "mq.topic";

    public static final String TRANSMISSION_LATENCY = "transmission.latency";

    /**
     * Tag, x-le(extension logic endpoint) series tag. Value is JSON format.
     *

     * {
     *   "name": "GraphQL-service",
     *   "latency": 100,
     *   "status": true
     * }
     *

     *
     * Also, could use value to indicate this local span is representing a logic endpoint.
     *

     * {
     *   "logic-span": true
     * }
     *

     */
    public static final String LOGIC_ENDPOINT = "x-le";
}

redpajama_set_name: RedPajamaGithub


text:
Anne Kennard, DO, completed a fellowship in integrative medicine. An ob-gyn, Dr. Kennard started teaching yoga to her pregnant patients to help them relieve their physical and emotional stress.
Beyond Medicine
Life outside medicine: These DOs paint, play music and raise chickens
Learn how creative pursuits, yoga and culinary education help some DOs find work-life balance.
By Nikitta Foston Email Wednesday, April 17, 2019
Anne Kennard, DO, has found similarities between teaching yoga and practicing as an osteopathic physician.
"They both require the same awareness of the intricacies of the body. Through gentle adjustments through osteopathic manipulative treatment (OMT) or fluid movements associated with yoga, the body is able to realign and heal itself," Dr. Kennard said. "Being a DO helps me be a better yoga teacher and being a yoga teacher helps me be a better DO."
Maintaining a well-balanced life outside of medicine is key to productivity within the profession, the DOs we spoke with say. Like Dr. Kennard, many DOs find that their outside passion replenishes their energy and gives them insights into medicine and patient care.
Anne Kennard, DO, is passionate about the integration of food and plants as medicine. She is currently training to become a clinical herbalist.
While in residency, she started teaching yoga to pregnant patients to help them relieve their physical and emotional stress. These days, she's a parent herself and conducts yoga clinics and teaches classes on healthy living and herbal medicine at a community college.
A member of the orchestra
Emergency medicine physician Jasper Yung, DO, started playing the violin in high school as a freshman but stopped playing for 18 years. After his residency, he started playing again. "I joined the Detroit Medical Orchestra, which gave me the opportunity to connect with the community and with music once again," Dr. Yung says.
The DMO was founded in 2009 by a then second-year medical student, Michelle Ubels, MD, who was also a musical conservatory graduate. The orchestra includes physicians, residents, medical students and other members of the health care profession.
Jasper Yung, DO, is a member of the Detroit Medical Orchestra. "Music allows me to personalize being a physician," he says.
There are similarities between music and medicine, Dr. Yung says. "Both carry restorative properties integral in healing one's self and one's community," he says.
For Dr. Yung, the greatest thing about being a violinist is being a part of something larger than himself. He loves that every note he plays serves to support the entire orchestra.
Before starting medical school, Valerie Staples, OMS IV, was a doula and childbirth educator. She's always believed that relaxation helps to calm the mind, body, and spirit. For Staples, that relaxation comes in the form of animals and lots of them. On what she describes as a mini-farm, Staples has several chickens, a donkey, five goats, a lizard, several dogs and a cockatoo she calls Dr. Loki Skylizard. The animals help Staples channel positive energy after an otherwise stressful day.
Valerie Staples, OMS IV, has a cockatoo, among several other animals. She says that connecting with her animals helps her to build a rapport with patients.
Staples refers to her chickens as therapy chickens. "I love to go outside, hang my hammock in the yard, and watch the chickens chase each other around the yard and beg me for snacks," Staples says. "They are very vocal, and they even sing a song when they lay an egg! I find it very relaxing just hanging out with them."
The animals are not only personally satisfying but also a wonderful way to connect with patients, Staples said. "You'd be surprised how many people keep backyard chickens, and it doesn't take long in a conversation to get them sharing about them," Staples said.
"I had a patient on my medical mission in Honduras who had injured himself pretty badly repairing his chicken coop, and when I told him I had chickens too, he seemed to relax and enjoy talking about his chickens while I helped stitch him up."
James Griffin, DO, started playing the bagpipes ten years ago. "I'm a musician who happens to be a physician," he says.
Bagpipe player
Ten years ago, James Griffin, DO, had never played a musical instrument nor read music. But his sister played the bagpipes and he was inspired to try it. Today, he's a bagpipe player and member of a band.
"Music provides an outlet from the stresses and responsibilities of medical practice, which is very important to maintain resiliency against burnout," Dr. Griffin says. "It is vitally important to have outside interests rather than identifying solely as a physician. Take an art class, travel, learn to dance or volunteer."
Dr. Griffin is the founding member and president of South County Anesthesia Associates, LLC in Wakefield, Rhode Island. He says that both music and medicine require specialized skills, which one spends a lifetime refining.
Amanda Emmert, DO, is a first-year psychiatry resident. She teaches culinary classes for children and serves as a leader in a children's nursery, part of the children's ministry at her church.
"The challenges of learning music and practicing medicine can seem insurmountable at times, but with perseverance and methodical training, one continually moves closer to the elusive goal of mastering them," he says.
Amanda Emmert, DO, is a first-year psychiatry resident at Creighton University. Her passion is helping children live healthier lives. In addition to teaching children about health and nutrition through cooking classes, she is also a teacher in a children's ministry.
Retired cardiologist and professor, Gary Hoff, now spends more time in his art studio. "Medicine is an art and so is painting."
"Most of the synapses our brain makes are developed in the first two years of life," Dr. Emmert says, "This is a really special population and it is so great watching how much they develop during that time. This impacts my medical pursuit because I get to spend time with the unique population that I will someday serve. I also get to experience interacting with families and understanding the family dynamic in each of their lives."
Artistry in action
Retired cardiologist and professor, Gary Hoff, DO, has been painting since he was 13 years old. After retiring, he decided to pursue his love for art in his studio full time.
"Having an interest outside of medicine allows a physician to be a whole, balanced person," he says.
How 2 DOs turned their passion for Broadway into producing a Tony Award-winning musical
Grey's Anatomy, Seinfeld and DO tattoos: Top people culture and lifestyle stories
off-call
How residents who gave birth navigate postgrad training and motherhood
As the number of women in medicine continues to grow, more physician moms are giving birth during residency.
A decade in review: Highlights in osteopathic medicine and the profession from 2010-2019
It's the end of the decade! Look back on some of the biggest moments in the osteopathic profession from the past 10 years.
Previous articleRestoring joy in the exam room: A DO's secret
Next articleJAOA cannabis study covered by CNN, Newsweek, Reuters, Vice and others
Ann Hupe, DO
Apr. 18, 2019, at 6:33 am
I've lived on a small-flock farm, raised organic lamb meat, sold wool of all sorts of colors to my friends who were spinners, and bred/raised/trained border collies as sheep herders, companion dogs, and seizure dogs. As I've told my patients: "A girl's gotta have a hobby."


text:
Q: Different block heights in tikzposter In the code example attached, I have created 2 columns and 2 rows with blocks (see the figure below). The first column and first row, denoted "Test1a" gets a shorter height than the other four blocks.

I presume that I have missed something in the "settings".
The code is listed below:
\documentclass[usenames,dvipsnames,a0paper, subcolspace = 3 mm, colspace = 3 mm, landscape, innermargin = 3 mm,  margin = 7 mm, blockhorizontalspace = 5 mm, blockverticalspace = 5 mm, 25 pt]{tikzposter}

\usetheme{Envelope} % See Section 5 (Rätt okej!)
\usecolorstyle[colorPalette=BrownBlueOrange]{Germany}

\tikzposterlatexaffectionproofoff

\begin{document}

\makeatletter
    \setlength{\TP@blocktop}{.495\textheight}
\makeatother

\settitle{ }

\begin{columns}
    \column{0.5}
    \colorlet{blockbodybgcolor}{MidnightBlue!100}
    \block[bodyoffsetx = 0 mm, bodyoffsety=-2cm,bodyverticalshift = 0 mm,bodyinnersep = 3 mm,titleinnersep = 0em,roundedcorners=0]{}{\color{white} \flushleft  \fontsize{60pt}{60pt}\selectfont Test1a}

    \column{0.5}
    \colorlet{blockbodybgcolor}{MidnightBlue!100}
    \block[bodyoffsetx = 0 mm, bodyoffsety=-2cm,bodyverticalshift = 0 mm,bodyinnersep = 3 mm,titleinnersep = 0em,roundedcorners=0]{}{\color{white} \flushleft  \fontsize{60pt}{60pt}\selectfont Test1b}
\end{columns}

\begin{columns}
    \column{0.3}
    \colorlet{blockbodybgcolor}{MidnightBlue!100}
    \block[bodyoffsetx = 0 mm, bodyoffsety=-2cm,bodyverticalshift = 0 mm,bodyinnersep = 3 mm,titleinnersep = 0em,roundedcorners=0]{}{\color{white} \flushleft  \fontsize{60pt}{60pt}\selectfont Test2a}

    \column{0.7}
    \colorlet{blockbodybgcolor}{MidnightBlue!100}
    \block[bodyoffsetx = 0 mm, bodyoffsety=-2cm,bodyverticalshift = 0 mm,bodyinnersep = 3 mm,titleinnersep = 0em,roundedcorners=0]{}{\color{white} \flushleft  \fontsize{60pt}{60pt}\selectfont Test2b}
\end{columns}

\end{document}

Can, please, someone help me out with that?
Thank you in advance!

A: No idea why exactly, but it works with \raggedright instead of \flushleft.
Unrelated things:

*

*there is no blockhorizontalspace class option, so that setting of yours doesn't do anything.

*Instead of adding \color{white} everywhere, you can set \colorlet{blockbodyfgcolor}{white}

\documentclass[
  usenames,
  dvipsnames,
  a2paper,
  subcolspace = 3 mm,
  colspace = 3 mm,
  landscape,
  innermargin = 3 mm,
  margin = 7 mm,
%  blockhorizontalspace = 5 mm, % this is not a valid option, doesn't do anything
  blockverticalspace = 5 mm,
  25 pt]{tikzposter}

\usetheme{Envelope} % See Section 5 (Rätt okej!)
\usecolorstyle[colorPalette=BrownBlueOrange]{Germany}

\tikzposterlatexaffectionproofoff

\begin{document}

\makeatletter
    \setlength{\TP@blocktop}{.495\textheight}
\makeatother

\settitle{ }
\colorlet{blockbodybgcolor}{MidnightBlue!100}
\colorlet{blockbodyfgcolor}{white} % color of text, no need for \color{white} everywhere
\begin{columns}
    \column{0.5}
    \block[bodyoffsetx = 0 mm,
           bodyoffsety=-2cm,
           bodyverticalshift = 0 mm,
           bodyinnersep = 3 mm,
           titleinnersep = 0em,
           roundedcorners=0]{}{\raggedright\fontsize{60pt}{60pt}\selectfont Test1a}

    \column{0.5}
    \block[bodyoffsetx = 0 mm,
           bodyoffsety=-2cm,
           bodyverticalshift = 0 mm,
           bodyinnersep = 3 mm,
           titleinnersep = 0em,
           roundedcorners=0]{}{\raggedright\fontsize{60pt}{60pt}\selectfont Test1b}
\end{columns}

\begin{columns}
    \column{0.3}
    \block[bodyoffsetx = 0 mm,
           bodyoffsety=-2cm,
           bodyverticalshift = 0 mm,
           bodyinnersep = 3 mm,
           titleinnersep = 0em,
           roundedcorners=0]{}{\raggedright\fontsize{60pt}{60pt}\selectfont Test2a}

    \column{0.7}
    \block[bodyoffsetx = 0 mm,
           bodyoffsety=-2cm,
           bodyverticalshift = 0 mm,
           bodyinnersep = 3 mm,
           titleinnersep = 0em,
           roundedcorners=0]{}{\raggedright \fontsize{60pt}{60pt}\selectfont Test2b}
\end{columns}

\end{document}

redpajama_set_name: RedPajamaStackExchange


It was getting late in the day at our little trade shop at the end of Miles Street, a dead-end street in an old mill town. We were just cleaning up, preparing to close for the day, when a large, gruff-looking man in coveralls came into the store. He walked with quick, broad, purposeful strides, right past the sales staff toward Joel's jewelers' bench. He was holding a steel mason's trowel, and his face was serious. "Hey. You know my wife, Roslyn?" he said abruptly, startling Joel from his bench work. Joel stuttered and fumbled for words, thinking the man was about to accuse him of having improper relations with his wife. "No," said Joel, "Uh, I don't think so." The man's face twisted, and he raised the mason's trowel toward Joel. "Do you think you could make one of these in gold?" he asked. Turns out his wife had a charm bracelet, and Charlie was hoping Joel could make a custom, handmade mason's trowel charm! Phew!