Skip to content
This repository has been archived by the owner on Jan 26, 2022. It is now read-only.

Commit

Permalink
Revert "Merge remote-tracking branch 'upstream/master'"
Browse files Browse the repository at this point in the history
This reverts commit a68c6d5, reversing
changes made to f7eb933.
  • Loading branch information
Aaron Triantafyllidis & Rick Reilly committed Sep 22, 2014
1 parent a68c6d5 commit 272986e
Show file tree
Hide file tree
Showing 39 changed files with 394 additions and 927 deletions.
14 changes: 9 additions & 5 deletions bin/common.sh
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
error() {
echo
echo " ! ERROR: $*" | indent no_first_line_indent
echo -n " ! ERROR: "
echo "$*" | indent
echo
exit 1
}

warning() {
echo
echo " ! WARNING: $*" | indent no_first_line_indent
echo -n " ! WARNING: "
echo "$*" | indent
echo "See https://devcenter.heroku.com/categories/php" | indent
echo
}

warning_inline() {
echo " ! WARNING: $*" | indent no_first_line_indent
echo -n " ! WARNING: "
echo "$*" | indent
}

status() {
Expand All @@ -22,6 +26,7 @@ status() {
notice() {
echo
echo "NOTICE: $*" | indent
echo "See https://devcenter.heroku.com/categories/php" | indent
echo
}

Expand All @@ -33,8 +38,7 @@ notice_inline() {
# so you get updates while the command runs and dont wait for the end
# e.g. npm install | indent
indent() {
# if an arg is given it's a flag indicating we shouldn't indent the first line, so use :+ to tell SED accordingly if that parameter is set, otherwise null string for no range selector prefix (it selects from line 2 onwards and then every 1st line, meaning all lines)
c="${1:+"2,999"} s/^/ /"
c='s/^/ /'
case $(uname) in
Darwin) sed -l "$c";; # mac/bsd sed: -l buffers on line boundaries
*) sed -u "$c";; # unix/gnu sed: -u unbuffered (arbitrary) chunks of data
Expand Down
218 changes: 84 additions & 134 deletions bin/compile

Large diffs are not rendered by default.

161 changes: 43 additions & 118 deletions bin/heroku-hhvm-apache2
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,20 @@
set -o pipefail
# fail harder
set -eu
# for ${DOCUMENT_ROOT%%*(/)} pattern further down
# for patterns further down
shopt -s extglob
# for detecting when -l 'logs/*.log' matches nothing
shopt -s nullglob

verbose=

php_passthrough() {
local dir=$(dirname "$1")
local file=$(basename "$1")
local out=$(basename "$file" .php)
local dir=$(dirname $1)
local file=$(basename $1)
local out=$(basename $file .php)
if [[ "$out" != "$file" ]]; then
[[ $verbose ]] && echo "Interpreting ${1#$HEROKU_APP_DIR/} to $out" >&2
echo "Interpreting ${1#$HEROKU_APP_DIR/} to $out" >&2
out="$dir/$out"
hhvm "$1" > "$out"
echo "$out"
hhvm $1 > $out
echo $out
else
echo "$1"
echo $1
fi
}

Expand All @@ -34,13 +30,9 @@ check_exists() {
fi
}

touch_log() {
mkdir -p $(dirname "$1") && touch "$1"
}

print_help() {
echo "\
${1:-Boots HHVM together with Apache2 on Heroku and for local development.}
Boots HHVM together with Apache2 on Heroku and for local development.
Usage:
heroku-hhvm-apache2 [options] [<DOCUMENT_ROOT>]
Expand All @@ -53,29 +45,22 @@ Options:
Recommended approach when customizing Apache2's config
in most cases, unless you need to set fundamental
server level options.
[default: \$COMPOSER_VENDOR_DIR/heroku/heroku-buildpack-php/conf/apache2/default_include.conf]
[default: $COMPOSER_VENDOR_DIR/heroku/heroku-buildpack-php/conf/apache2/default_include.conf]
-c <httpd.conf> The path to the full VHost configuration file that is
included after Heroku's (or your local) Apache2 config
is loaded. Must contain a 'Listen \${PORT}' directive
and should have a '<VirtualHost>' and likely also a
'<Directory>' section (see option -C above).
[default: \$COMPOSER_VENDOR_DIR/heroku/heroku-buildpack-php/conf/apache2/heroku.conf]
-h, --help Display this help screen and exit.
[default: $COMPOSER_VENDOR_DIR/heroku/heroku-buildpack-php/conf/apache2/heroku.conf]
-h Display this help screen and exit.
-i <php.ini> The path to the php.ini file to use.
[default: \$COMPOSER_VENDOR_DIR/heroku/heroku-buildpack-php/conf/hhvm/php.ini]
-l <tailme.log> Path to additional log file to tail to STDERR so its
contents appear in 'heroku logs'. If the file does not
exist, it will be created. Wildcards are allowed, but
must be quoted and must match already existing files.
Note: this option can be repeated multiple times.
-v, --verbose Be more verbose during startup.
All file paths must be relative to '$HEROKU_APP_DIR'.
[default: $COMPOSER_VENDOR_DIR/heroku/heroku-buildpack-php/conf/hhvm/php.ini]
Any file name that ends in '.php' will be run through the PHP interpreter first.
You may use this for templating although this is less useful than e.g. for Nginx
where unlike in Apache2, you cannot reference environment variables in config
files using a '\${VARNAME}' syntax.
All file paths must be relative to '$HEROKU_APP_DIR'.
If you would like to use the -C and -c options together, make sure you retain
the appropriate include mechanisms (see default configs for details).
Expand All @@ -87,42 +72,10 @@ export HEROKU_APP_DIR=$(pwd)
export DOCUMENT_ROOT="$HEROKU_APP_DIR"
# set a default port if none is given
export PORT=${PORT:-$(( $RANDOM+1024 ))}
export COMPOSER_VENDOR_DIR=$(composer config vendor-dir 2> /dev/null | tail -n 1) # tail, as composer echos outdated version warnings to STDOUT
export COMPOSER_BIN_DIR=$(composer config bin-dir 2> /dev/null | tail -n 1) # tail, as composer echos outdated version warnings to STDOUT

# our standard logs
logs=( "/tmp/heroku.apache2_error.$PORT.log" "/tmp/heroku.apache2_access.$PORT.log" )

optstring=":-:C:c:i:l:vh"

# process flags first
while getopts "$optstring" opt; do
case $opt in
-)
case "$OPTARG" in
verbose)
verbose=1
;;
help)
print_help 2>&1
exit
;;
*)
echo "Invalid option: --$OPTARG" >&2
exit
;;
esac
;;
v)
verbose=1
;;
h)
print_help 2>&1
exit
;;
esac
done

OPTIND=1 # start over with options parsing
while getopts "$optstring" opt; do
while getopts ":C:c:i:h" opt; do
case $opt in
C)
httpd_config_include=$(check_exists "$OPTARG" "C")
Expand All @@ -133,21 +86,9 @@ while getopts "$optstring" opt; do
i)
php_config=$(check_exists "$OPTARG" "i")
;;
l)
logarg=( $OPTARG ) # must not quote this or wildcards won't get expanded into individual values
if [[ ${#logarg[@]} -eq 0 ]]; then # we set nullglob to detect if a pattern matched nothing (then the array is empty)
echo "Pattern '$OPTARG' passed to option -l matched no files" >&2
exit 1
fi
for logfile in "${logarg[@]}"; do
if [[ -d "$logfile" ]]; then
echo "-l '$logfile': is a directory" >&2
exit 1
fi
touch_log "$logfile" || { echo "Could not touch '$logfile'; permissions problem?" >&2; exit 1; }
[[ $verbose ]] && echo "Tailing '$logfile' to stderr" >&2
logs+=("$logfile") # must quote here in case a wildcard matched a file with a space in the name
done
h)
print_help 2>&1
exit
;;
\?)
echo "Invalid option: -$OPTARG" >&2
Expand All @@ -163,53 +104,39 @@ done
shift $((OPTIND-1))

if [[ "$#" -gt "1" ]]; then
print_help "$0: too many arguments. If you're using options,
make sure to list them before any document root argument you're providing."
print_help
exit 2
fi

hhvm --php -r 'exit((int)version_compare(HHVM_VERSION, "3.0.1", "<"));' || { echo "This program requires HHVM 3.0.1 or newer" >&2; exit 1; }
{ { httpd -v | hhvm --php -r 'exit((int)version_compare(preg_replace("#^Server version: Apache/(\S+).+$#sm", "\\1", file_get_contents("php://stdin")), "2.4.10", "<"));'; } && { httpd -t -D DUMP_MODULES | grep 'proxy_fcgi_module' > /dev/null; }; } || { echo "This program requires Apache 2.4.10 or newer with mod_proxy and mod_proxy_fcgi enabled; check your 'httpd' command." >&2; exit 1; }

# make sure we run a local composer.phar if present, or global composer if not
composer() {
hhvm $(which ./composer.phar composer | head -n1) "$@"
}
COMPOSER_VENDOR_DIR=$(composer config vendor-dir 2> /dev/null | tail -n 1) && export COMPOSER_VENDOR_DIR || { echo "Unable to determine Composer vendor-dir setting; is 'composer' executable on path or 'composer.phar' in current working directory?"; exit 1; } # tail, as composer echos outdated version warnings to STDOUT; export after the assignment or exit status will that be of 'export
COMPOSER_BIN_DIR=$(composer config bin-dir 2> /dev/null | tail -n 1) && export COMPOSER_BIN_DIR || { echo "Unable to determine Composer vendor-dir setting; is 'composer' executable on path or 'composer.phar' in current working directory?"; exit 1; } # tail, as composer echos outdated version warnings to STDOUT; export after the assignment or exit status will that be of 'export
{ { httpd -v | hhvm --php -r 'exit((int)version_compare(preg_replace("#^Server version: Apache/(\S+).+$#sm", "\\1", file_get_contents("php://stdin")), "2.4.8", "<"));'; } && { httpd -t -D DUMP_MODULES | awk '/proxy_fcgi_module/ {f1=1} /rewrite_module/ {f2=1} END {exit !(f1 && f2)}'; }; } || { echo "This program requires Apache 2.4.8 or newer with mod_proxy, mod_proxy_fcgi and mod_rewrite enabled; check your 'httpd' command." >&2; exit 1; }
{ { httpd -v | php -r 'exit((int)version_compare(preg_replace("#^Server version: Apache/(\S+).+$#sm", "\\1", file_get_contents("php://stdin")), "2.4.10", "<"));'; } || { httpd -t -D DUMP_MODULES | grep 'proxy_handler_module' > /dev/null; }; } || { echo "This program requires mod_proxy_handler for Apache versions before 2.4.10; you may install it from https://gist.github.com/progandy/6ed4eeea60f6277c3e39"; exit 1; }

[[ -z ${DYNO:-} || $verbose ]] && echo "Booting on port $PORT..." >&2
echo "Booting on port $PORT..." >&2

if [[ "$#" == "1" ]]; then
DOCUMENT_ROOT="$HEROKU_APP_DIR/$1"
if [[ ! -d "$DOCUMENT_ROOT" ]]; then
echo "DOCUMENT_ROOT '$1' does not exist" >&2
echo "DOCUMENT_ROOT '$1' does not exist"
exit 1
else
# strip trailing slashes if present
DOCUMENT_ROOT=${DOCUMENT_ROOT%%*(/)} # powered by extglob
if [[ $verbose ]]; then
echo "DOCUMENT_ROOT changed to '$DOCUMENT_ROOT'" >&2
else
echo "DOCUMENT_ROOT changed to '${1%%*(/)}/'" >&2
fi
DOCUMENT_ROOT=${DOCUMENT_ROOT%%*(/)}
echo "DOCUMENT_ROOT changed to '$DOCUMENT_ROOT'" >&2
fi
fi

if [[ -n ${php_config:-} || ( ${php_config:="$HEROKU_APP_DIR/$COMPOSER_VENDOR_DIR/heroku/heroku-buildpack-php/conf/hhvm/php.ini"} && $verbose ) ]]; then
echo "Using HHVM configuration (php.ini) file '${php_config#$HEROKU_APP_DIR/}'" >&2
fi
php_config=${php_config:-"$HEROKU_APP_DIR/$COMPOSER_VENDOR_DIR/heroku/heroku-buildpack-php/conf/hhvm/php.ini"}
echo "Using HHVM configuration (php.ini) file '${php_config#$HEROKU_APP_DIR/}'" >&2
php_config=$(php_passthrough "$php_config")

if [[ -n ${httpd_config_include:-} || ( ${httpd_config_include:="$HEROKU_APP_DIR/$COMPOSER_VENDOR_DIR/heroku/heroku-buildpack-php/conf/apache2/default_include.conf"} && $verbose ) ]]; then
echo "Using Apache2 VirtualHost-level configuration include '${httpd_config_include#$HEROKU_APP_DIR/}'" >&2
fi
httpd_config_include=${httpd_config_include:-"$HEROKU_APP_DIR/$COMPOSER_VENDOR_DIR/heroku/heroku-buildpack-php/conf/apache2/default_include.conf"}
echo "Using Apache2 VirtualHost-level configuration include '${httpd_config_include#$HEROKU_APP_DIR/}'" >&2
httpd_config_include=$(php_passthrough "$httpd_config_include")
export HEROKU_PHP_HTTPD_CONFIG_INCLUDE="$httpd_config_include"

if [[ -n ${httpd_config:-} || ( ${httpd_config:="$HEROKU_APP_DIR/$COMPOSER_VENDOR_DIR/heroku/heroku-buildpack-php/conf/apache2/heroku.conf"} && $verbose) ]]; then
echo "Using Apache2 configuration file '${httpd_config#$HEROKU_APP_DIR/}'" >&2
fi
httpd_config=${httpd_config:-"$HEROKU_APP_DIR/$COMPOSER_VENDOR_DIR/heroku/heroku-buildpack-php/conf/apache2/heroku.conf"}
echo "Using Apache2 configuration file '${httpd_config#$HEROKU_APP_DIR/}'" >&2
httpd_config=$(php_passthrough "$httpd_config")

# make a shared pipe; we'll write the name of the process that exits to it once that happens, and wait for that event below
Expand All @@ -220,30 +147,28 @@ mkfifo $wait_pipe

# trap SIGINT/SIGQUIT (ctrl+c or ctrl+\ on the console), SIGTERM, and EXIT (upon failure of any command due to set -e, or because of the exit 1 at the very end), kill subshell child processes, then subshells
# 1) restore EXIT trap immediately, or the exit at the end of the line will trigger this trap again
# 2) kill childrens' child processes (the stuff running inside the sub-shells) using xargs because this is easier (-P expects a comma separated list); the || true prevents premature exit (set -e) if one of those doesn't have children anymore (it's likely that's why we're hitting this bit of code in the first place), and redirect all to /dev/null as usage help when no args given (because jobs -p was empty) is sometimes (Linux) printed to STDOUT
# 2) kill childrens' child processes (the stuff running inside the sub-shells) using xargs because this is easier (-P expects a comma separated list); the || true prevents premature exit (set -e) if one of those doesn't have children anymore (it's likely that's why we're hitting this bit of code in the first place)
# 3) kill child processes (that's the sub-shells); it's likely that some of them have already disappeared, so xarg || true it too and suppress "no such process" complaints by sending them to /dev/null
# FIXME: this doesn't currently fire when the subshells themselves are terminated
# FIXME: this doesn't currently fire when the subshells themselves are terminated, and apparently also not when killing the tail command
# TODO: for extra brownie points, move to a function and curry for each given signal, passing the signal in as an arg, so we can use different exit codes or messages
trap 'trap - EXIT; echo "Going down, terminating child processes..." >&2; jobs -p | xargs -n1 pkill -TERM -P &> /dev/null || true; jobs -p | xargs -n1 kill -TERM 2> /dev/null || true; exit' SIGINT SIGQUIT SIGTERM EXIT

# launch processes. all run using || true to prevent premature exit of the subshell (from set -e) regardless of exit status
# after a subprocess terminates (because it was killed or because it crashed or because it quit voluntarily), we write the name to FD 3 (because programs could output something on FD 1 (STDOUT) or FD 2 (STDERR)) and send that to the shared pipe (mkfifo) above, and a read command further down waits for something to come in on the shared pipe
trap 'trap - EXIT; echo "Going down, terminating child processes..." >&2; jobs -p | xargs -n1 pkill -TERM -P || true; jobs -p | xargs -n1 kill -TERM 2> /dev/null || true; exit' SIGINT SIGQUIT SIGTERM EXIT

# redirect logs to STDERR; write "tail ..." to the shared pipe if it exits
[[ $verbose ]] && echo "Starting log redirection..." >&2
( touch "${logs[@]}"; tail -qF -n 0 "${logs[@]}" 1>&2 || true; echo 'tail "${logs[@]}"' >&3; ) 3> $wait_pipe &
echo "Starting log redirection..." >&2
( touch "/tmp/heroku.apache2_error.$PORT.log" "/tmp/heroku.apache2_access.$PORT.log"; tail -qF -n 0 /tmp/heroku.*.$PORT.log 1>&2; echo "tail heroku.*.$PORT.log"; ) > $wait_pipe &
# start HHVM; write "hhvm" to the shared pipe if it exits
# (it writes to STDOUT, we need to redirect to STDERR)
echo "Starting hhvm..." >&2
( hhvm --mode server -vServer.Type=fastcgi -vServer.FileSocket=/tmp/heroku.fcgi.$PORT.sock -c "$php_config" || true; echo "hhvm" >&3; ) 3> $wait_pipe &
( hhvm --mode server -vServer.Type=fastcgi -vServer.FileSocket=/tmp/heroku.fcgi.$PORT.sock -c "$php_config" >&2; echo "hhvm"; ) > $wait_pipe &
# wait a few seconds for HHVM to finish initializing; otherwise an early request might break Apache with the FastCGI pipe not being ready
# start apache; write "httpd" to the shared pipe if it exits
echo "Starting httpd..." >&2
( sleep 2; httpd -D NO_DETACH -c "Include $httpd_config" || true; echo "httpd" >&3; ) 3> $wait_pipe &
( sleep 2; httpd -D NO_DETACH -c "Include $httpd_config" || true; echo "httpd"; ) > $wait_pipe &

# wait for something to come from the shared pipe, which means that the given process was killed or has failed
read exitproc < $wait_pipe
# we'll only reach this if one of the processes above has terminated
echo "Process exited unexpectedly: $exitproc" >&2
read exitproc < $wait_pipe
echo "Process exited unexpectedly: $exitproc"

# this will trigger the trap and kill all remaining children
exit 1
Loading

0 comments on commit 272986e

Please sign in to comment.