diff options
author | David 'Digit' Turner <digit@google.com> | 2009-05-26 17:07:25 +0200 |
---|---|---|
committer | David 'Digit' Turner <digit@google.com> | 2009-05-26 17:07:25 +0200 |
commit | 303659072cc188102a8261f5c799980d477fd479 (patch) | |
tree | bce721be46821f837917506bf451f1299542eb7b | |
parent | 6ca13900eb5b9d7a8a59925f2bb6c35adc0613d0 (diff) | |
download | sdk-303659072cc188102a8261f5c799980d477fd479.zip sdk-303659072cc188102a8261f5c799980d477fd479.tar.gz sdk-303659072cc188102a8261f5c799980d477fd479.tar.bz2 |
This adds a new helper program (qemu-props) to support the emulated system.
Its purpose is to contact the 'boot-properties' service during the
boot process and to set the list of system properties read from the
emulator program through it.
It must be launched from /system/etc/init.goldfish.rc as root.
It depends on the 'boot-properties' service being implemented by the
emulator (in a later patch). If not available, it will simply timeout.
This also fixes a potential crash in qemud which can happen in the following case:
- client sends a command to a service
- the service responds with one or more message
- the service immediately closes the connection before the client can read the data
what happened is that the FDHandler object was buffering out-going packets to the
client, but the Multiplexer acted on the disconnection immediately. This resulted
in:
- client_free() being called
- fdhandler_shutdown() being called
- the FDHandler being placed on the 'closing' list to be able to send
buffered packets later. And 'receiver_close' being called
- client_fd_close() being called, which would call client_free()
recursively
- the second client_free() call would free the object
- the first client_free() call would try to free the object again
- ==> dlmalloc() detects a double-free and immediately aborts.
the fixes simply avoids the calle to receiver_close() in fdhandler_shutdown()
since this function is called from an explicit shutdown request from the multiplexer,
it doesn't correspond to the case where the client has closed the connection itself.
-rw-r--r-- | emulator/qemud/qemud.c | 6 | ||||
-rw-r--r-- | emulator/tools/Android.mk | 36 | ||||
-rw-r--r-- | emulator/tools/qemu-props.c | 114 |
3 files changed, 154 insertions, 2 deletions
diff --git a/emulator/qemud/qemud.c b/emulator/qemud/qemud.c index c578145..5edf8a6 100644 --- a/emulator/qemud/qemud.c +++ b/emulator/qemud/qemud.c @@ -857,8 +857,10 @@ fdhandler_shutdown( FDHandler* f ) fdhandler_remove(f); fdhandler_prepend(f, &f->list->closing); - /* notify the receiver that we're closing */ - receiver_close(f->receiver); + /* prevent later fdhandler_close() to + * call the receiver's close. + */ + f->receiver->close = NULL; return; } diff --git a/emulator/tools/Android.mk b/emulator/tools/Android.mk new file mode 100644 index 0000000..c9d9613 --- /dev/null +++ b/emulator/tools/Android.mk @@ -0,0 +1,36 @@ +# Copyright (C) 2009 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# this file is used to build emulator-specific program tools +# that should only run in the emulator. +# + +LOCAL_PATH := $(call my-dir) + +ifneq ($(TARGET_PRODUCT),sim) + +# The 'qemu-props' program is run from /system/etc/init.goldfish.rc +# to setup various system properties sent by the emulator program. +# +include $(CLEAR_VARS) +LOCAL_MODULE := qemu-props +LOCAL_SRC_FILES := qemu-props.c +LOCAL_SHARED_LIBRARIES := libcutils +# we don't want this in 'user' builds which don't have +# emulator-specific binaries. +LOCAL_MODULE_TAGS := debug +include $(BUILD_EXECUTABLE) + +endif # TARGET_PRODUCT != sim + diff --git a/emulator/tools/qemu-props.c b/emulator/tools/qemu-props.c new file mode 100644 index 0000000..09105fc --- /dev/null +++ b/emulator/tools/qemu-props.c @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* this program is used to read a set of system properties and their values + * from the emulator program and set them in the currently-running emulated + * system. It does so by connecting to the 'boot-properties' qemud service. + * + * This program should be run as root and called from + * /system/etc/init.goldfish.rc exclusively. + */ + +#define LOG_TAG "qemu-props" + +#define DEBUG 1 + +#if DEBUG +# include <cutils/log.h> +# define DD(...) LOGI(__VA_ARGS__) +#else +# define DD(...) ((void)0) +#endif + +#include <cutils/properties.h> +#include <unistd.h> +#include <hardware/qemud.h> + +/* Name of the qemud service we want to connect to. + */ +#define QEMUD_SERVICE "boot-properties" + +#define MAX_TRIES 5 + +int main(void) +{ + int qemud_fd, count = 0; + + /* try to connect to the qemud service */ + { + int tries = MAX_TRIES; + + while (1) { + qemud_fd = qemud_channel_open( "boot-properties" ); + if (qemud_fd >= 0) + break; + + if (--tries <= 0) { + DD("Could not connect after too many tries. Aborting"); + return 1; + } + + DD("waiting 1s to wait for qemud."); + sleep(1); + } + } + + DD("connected to '%s' qemud service.", QEMUD_SERVICE); + + /* send the 'list' command to the service */ + if (qemud_channel_send(qemud_fd, "list", -1) < 0) { + DD("could not send command to '%s' service", QEMUD_SERVICE); + return 1; + } + + /* read each system property as a single line from the service, + * until exhaustion. + */ + for (;;) + { +#define BUFF_SIZE (PROPERTY_KEY_MAX + PROPERTY_VALUE_MAX + 2) + + char* q; + char temp[BUFF_SIZE]; + int len = qemud_channel_recv(qemud_fd, temp, sizeof temp - 1); + + if (len < 0 || len > BUFF_SIZE-1) + break; + + temp[len] = '\0'; /* zero-terminate string */ + + DD("received: %.*s", len, temp); + + /* separate propery name from value */ + q = strchr(temp, '='); + if (q == NULL) { + DD("invalid format, ignored."); + continue; + } + *q++ = '\0'; + + if (property_set(temp, q) < 0) { + DD("could not set property '%s' to '%s'", temp, q); + } else { + count += 1; + } + } + + /* finally, close the channel and exit */ + close(qemud_fd); + DD("exiting (%d properties set).", count); + return 0; +} |