X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fsgen%2Fsgen-protocol.c;h=2e59b6359a4b1aea6f4e650998ae1590e4318d50;hb=cadf391beab4c0d0c4aada7acb8fcb7c2e702e87;hp=4ea1ac391c9a4e083a5fa3f842d1e8ed3548ff53;hpb=bd52e33266aee6ffbddf313a99db7fffc497a095;p=mono.git diff --git a/mono/sgen/sgen-protocol.c b/mono/sgen/sgen-protocol.c index 4ea1ac391c9..2e59b6359a4 100644 --- a/mono/sgen/sgen-protocol.c +++ b/mono/sgen/sgen-protocol.c @@ -6,18 +6,7 @@ * Copyright 2003-2010 Novell, Inc. * Copyright (C) 2012 Xamarin Inc * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License 2.0 as published by the Free Software Foundation; - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License 2.0 along with this library; if not, write to the Free - * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Licensed under the MIT license. See LICENSE file in the project root for full license information. */ #ifdef HAVE_SGEN_GC @@ -30,6 +19,7 @@ #include "sgen-thread-pool.h" #include "sgen-client.h" #include "mono/utils/mono-membar.h" +#include "mono/utils/mono-proclib.h" #include #include @@ -69,7 +59,7 @@ filename_for_index (int index) SGEN_ASSERT (0, file_size_limit > 0, "Indexed binary protocol filename must only be used with file size limit"); - filename = sgen_alloc_internal_dynamic (strlen (filename_or_prefix) + 32, INTERNAL_MEM_BINARY_PROTOCOL, TRUE); + filename = (char *)sgen_alloc_internal_dynamic (strlen (filename_or_prefix) + 32, INTERNAL_MEM_BINARY_PROTOCOL, TRUE); sprintf (filename, "%s.%d", filename_or_prefix, index); return filename; @@ -84,9 +74,16 @@ free_filename (char *filename) } static void -binary_protocol_open_file (void) +binary_protocol_open_file (gboolean assert_on_failure) { char *filename; +#ifdef F_SETLK + struct flock lock; + lock.l_type = F_WRLCK; + lock.l_whence = SEEK_SET; + lock.l_start = 0; + lock.l_len = 0; +#endif if (file_size_limit > 0) filename = filename_for_index (current_file_index); @@ -94,11 +91,26 @@ binary_protocol_open_file (void) filename = filename_or_prefix; do { - binary_protocol_file = open (filename, O_CREAT|O_WRONLY|O_TRUNC, 0644); - if (binary_protocol_file == -1 && errno != EINTR) - break; /* Failed */ + binary_protocol_file = open (filename, O_CREAT | O_WRONLY, 0644); + if (binary_protocol_file == -1) { + if (errno != EINTR) + break; /* Failed */ +#ifdef F_SETLK + } else if (fcntl (binary_protocol_file, F_SETLK, &lock) == -1) { + /* The lock for the file is already taken. Fail */ + close (binary_protocol_file); + binary_protocol_file = -1; + break; +#endif + } else { + /* We have acquired the lock. Truncate the file */ + ftruncate (binary_protocol_file, 0); + } } while (binary_protocol_file == -1); + if (binary_protocol_file == -1 && assert_on_failure) + g_error ("sgen binary protocol: failed to open file"); + if (file_size_limit > 0) free_filename (filename); } @@ -108,12 +120,27 @@ void binary_protocol_init (const char *filename, long long limit) { #ifdef HAVE_UNISTD_H - filename_or_prefix = sgen_alloc_internal_dynamic (strlen (filename) + 1, INTERNAL_MEM_BINARY_PROTOCOL, TRUE); - strcpy (filename_or_prefix, filename); - file_size_limit = limit; - binary_protocol_open_file (); + /* Original name length + . + pid length in hex + null terminator */ + filename_or_prefix = g_strdup_printf ("%s", filename); + binary_protocol_open_file (FALSE); + + if (binary_protocol_file == -1) { + /* Another process owns the file, try adding the pid suffix to the filename */ + gint32 pid = mono_process_current_pid (); + g_free (filename_or_prefix); + filename_or_prefix = g_strdup_printf ("%s.%x", filename, pid); + binary_protocol_open_file (TRUE); + } + + /* If we have a file size limit, we might need to open additional files */ + if (file_size_limit == 0) + g_free (filename_or_prefix); + + binary_protocol_header (PROTOCOL_HEADER_CHECK, PROTOCOL_HEADER_VERSION, SIZEOF_VOID_P, G_BYTE_ORDER == G_LITTLE_ENDIAN); +#else + g_error ("sgen binary protocol: not supported"); #endif } @@ -224,7 +251,7 @@ binary_protocol_check_file_overflow (void) ++current_file_index; current_file_size = 0; - binary_protocol_open_file (); + binary_protocol_open_file (TRUE); } #endif @@ -251,7 +278,7 @@ binary_protocol_flush_buffers (gboolean force) for (buf = binary_protocol_buffers; buf != NULL; buf = buf->next) ++num_buffers; - bufs = sgen_alloc_internal_dynamic (num_buffers * sizeof (BinaryProtocolBuffer*), INTERNAL_MEM_BINARY_PROTOCOL, TRUE); + bufs = (BinaryProtocolBuffer **)sgen_alloc_internal_dynamic (num_buffers * sizeof (BinaryProtocolBuffer*), INTERNAL_MEM_BINARY_PROTOCOL, TRUE); for (buf = binary_protocol_buffers, i = 0; buf != NULL; buf = buf->next, i++) bufs [i] = buf; SGEN_ASSERT (0, i == num_buffers, "Binary protocol buffer count error"); @@ -280,7 +307,7 @@ binary_protocol_get_buffer (int length) if (buffer && buffer->index + length <= BINARY_PROTOCOL_BUFFER_SIZE) return buffer; - new_buffer = sgen_alloc_os_memory (sizeof (BinaryProtocolBuffer), SGEN_ALLOC_INTERNAL | SGEN_ALLOC_ACTIVATE, "debugging memory"); + new_buffer = (BinaryProtocolBuffer *)sgen_alloc_os_memory (sizeof (BinaryProtocolBuffer), (SgenAllocFlags)(SGEN_ALLOC_INTERNAL | SGEN_ALLOC_ACTIVATE), "debugging memory"); new_buffer->next = buffer; new_buffer->index = 0;