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.
This commit is contained in:
David 'Digit' Turner
2009-05-26 17:07:25 +02:00
parent 3a39e9c90b
commit af45b39d88
3 changed files with 154 additions and 2 deletions

View File

@@ -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;
}

36
emulator/tools/Android.mk Normal file
View File

@@ -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

114
emulator/tools/qemu-props.c Normal file
View File

@@ -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;
}