aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--conf/distro/slugos.conf6
-rw-r--r--recipes/opkg/files/opkg_use_vfork_gunzip.patch139
-rw-r--r--recipes/opkg/opkg.inc2
-rw-r--r--recipes/opkg/opkg_svn.bb1
4 files changed, 144 insertions, 4 deletions
diff --git a/conf/distro/slugos.conf b/conf/distro/slugos.conf
index 96c2f45893..049e24ebed 100644
--- a/conf/distro/slugos.conf
+++ b/conf/distro/slugos.conf
@@ -11,9 +11,9 @@ DISTRO_NAME = "SlugOS"
DISTRO_TYPE = "alpha"
TARGET_ARCH ?= "armeb"
ARM_INSTRUCTION_SET = "thumb"
-IPKG_VARIANT ?= "opkg-nogpg-nocurl-slugos"
-PREFERRED_PROVIDER_opkg ?= "opkg-nogpg-nocurl-slugos"
-PREFERRED_PROVIDER_virtual/update-alternatives ?= "opkg-nogpg-nocurl-slugos"
+IPKG_VARIANT ?= "opkg"
+PREFERRED_PROVIDER_opkg ?= "opkg"
+PREFERRED_PROVIDER_virtual/update-alternatives ?= "opkg"
IMAGE_INITSCRIPTS ?= "initscripts-slugos"
IMAGE_DEV_MANAGER = "udev"
# Disable installing ldconfig
diff --git a/recipes/opkg/files/opkg_use_vfork_gunzip.patch b/recipes/opkg/files/opkg_use_vfork_gunzip.patch
new file mode 100644
index 0000000000..d9c40df840
--- /dev/null
+++ b/recipes/opkg/files/opkg_use_vfork_gunzip.patch
@@ -0,0 +1,139 @@
+# This patch allows a user to set an environment variable to cause opkg to
+# select either the built-in gunzip code or an external gunzip utility, in
+# order to dodge the OOM Killer.
+#
+# The built-in code is, of course, is the most desirable way to use opkg,
+# since it is far more efficient. However, the built-in code can trigger
+# the OOM (out of memory) killer on small-memory machines, like the 32MB
+# NSLU2. This occurs because a standard fork will duplicate the entire
+# address space of the parent. Since opkg reads the entire feed database
+# into memory, this problem is compounded by large feeds.
+#
+# This patch introduces a means for the user to cause opkg to use vfork()
+# instead -- vfork() does not behave in the same manner as fork(), and
+# does not trigger the OOM killer. However, the semantics of vfork() are
+# such that it cannot run the built-in gunzip code. Instead, it must
+# exec() an external utility to perform the gunzip operation. It seems
+# counter-intuitive, but the vfork()/exec() approach is the only good way
+# to avoid triggering the dreaded OOM killer.
+#
+# In order to use this, the user must manually set the OPKG_USE_VFORK
+# environment variable to any value. For example:
+#
+# $ OPKG_USE_VFORK=1 opkg install samba
+#
+# The external utility used to do the gunzip operation is "busybox gunzip".
+# It would have been nice to be able to just invoke "gunzip", but the
+# full gunzip executable behaves slightly differently than does busybox,
+# generating annoying warning messages.
+#
+# This is an update of the original patch by Mike Westerhof, Dec 2008.
+#
+# Mike Westerhof, Feb 2011
+#
+--- orig/libbb/gz_open.c 2011-02-12 10:58:02.035287826 -0600
++++ opkg/libbb/gz_open.c 2011-02-12 11:51:12.120033055 -0600
+@@ -29,10 +29,29 @@
+ #include <unistd.h>
+ #include "libbb.h"
+
++int
++gz_use_vfork()
++{
++ char *v = getenv("OPKG_USE_VFORK");
++ return (v != NULL);
++}
++
+ FILE *
+ gz_open(FILE *compressed_file, int *pid)
+ {
+ int unzip_pipe[2];
++ off_t floc;
++ int cfile;
++
++ if (gz_use_vfork()) {
++ /* Create a new file descriptor for the input stream
++ * (it *must* be associated with a file), and lseek()
++ * to the same position in that fd as the stream.
++ */
++ cfile = dup(fileno(compressed_file));
++ floc = ftello(compressed_file);
++ lseek(cfile, floc, SEEK_SET);
++ }
+
+ if (pipe(unzip_pipe)!=0) {
+ perror_msg("pipe");
+@@ -44,18 +63,37 @@
+ fflush(stdout);
+ fflush(stderr);
+
+- if ((*pid = fork()) == -1) {
++ if (gz_use_vfork()) {
++ *pid = vfork();
++ } else {
++ *pid = fork();
++ }
++
++ if (*pid<0) {
+ perror_msg("fork");
+ return(NULL);
+ }
++
+ if (*pid==0) {
+ /* child process */
+ close(unzip_pipe[0]);
+- unzip(compressed_file, fdopen(unzip_pipe[1], "w"));
+- fflush(NULL);
+- fclose(compressed_file);
+- close(unzip_pipe[1]);
+- _exit(EXIT_SUCCESS);
++ if (gz_use_vfork()) {
++ dup2(unzip_pipe[1], 1);
++ dup2(cfile, 0);
++ execlp("busybox","busybox","gunzip",NULL);
++ /* If we get here, we had a failure */
++ _exit(EXIT_FAILURE);
++ } else {
++ unzip(compressed_file, fdopen(unzip_pipe[1], "w"));
++ fflush(NULL);
++ fclose(compressed_file);
++ close(unzip_pipe[1]);
++ _exit(EXIT_SUCCESS);
++ }
++ }
++ /* Parent process is executing here */
++ if (gz_use_vfork()) {
++ close(cfile);
+ }
+ close(unzip_pipe[1]);
+ return(fdopen(unzip_pipe[0], "r"));
+@@ -67,11 +105,29 @@
+ int status;
+ int ret;
+
++ if (gz_use_vfork()) {
++ /* The gunzip process remains running in the background if we
++ * used the vfork()/exec() technique - so we have to kill it
++ * forcibly. There might be a better way to do this, but that
++ * affect a lot of other parts of opkg, and this works fine.
++ */
++ if (kill(gunzip_pid, SIGTERM) == -1) {
++ perror_msg("gz_close(): unable to kill gunzip pid.");
++ return -1;
++ }
++ }
++
++
+ if (waitpid(gunzip_pid, &status, 0) == -1) {
+ perror_msg("waitpid");
+ return -1;
+ }
+
++ if (gz_use_vfork()) {
++ /* Bail out here if we used the vfork()/exec() technique. */
++ return 0;
++ }
++
+ if (WIFSIGNALED(status)) {
+ error_msg("Unzip process killed by signal %d.\n",
+ WTERMSIG(status));
diff --git a/recipes/opkg/opkg.inc b/recipes/opkg/opkg.inc
index c0025c086d..a4878e2151 100644
--- a/recipes/opkg/opkg.inc
+++ b/recipes/opkg/opkg.inc
@@ -5,7 +5,7 @@ LICENSE = "GPLv2"
SRCREV = "599"
PV = "0.1.8+svnr${SRCPV}"
CONFLICTS = "ipkg"
-INC_PR = "r3"
+INC_PR = "r4"
SRC_URI = "svn://opkg.googlecode.com/svn;module=trunk;proto=http \
file://configure \
diff --git a/recipes/opkg/opkg_svn.bb b/recipes/opkg/opkg_svn.bb
index 7ea15105d4..cc377b755e 100644
--- a/recipes/opkg/opkg_svn.bb
+++ b/recipes/opkg/opkg_svn.bb
@@ -2,6 +2,7 @@ require opkg.inc
PR = "${INC_PR}"
+SRC_URI_append_slugos = " file://opkg_use_vfork_gunzip.patch"
PROVIDES =+ "virtual/update-alternatives"
RPROVIDES_${PN} = "update-alternatives"