Skip to content

Commit

Permalink
[mono] Move basic w32file* and w32process* functions to eventpipe
Browse files Browse the repository at this point in the history
They are not used by the rest of the runtime and we only need a bare minimum of w32process and w32file in eventpipe (e.g. no file share/access logic).

Fix ep-test build and warnings, it was missing linking against libz and monoapi.

Fix host vs. target confusion in ep-rt-mono.c
  • Loading branch information
akoeplinger committed Mar 16, 2022
1 parent a1f1ab8 commit e82c20a
Show file tree
Hide file tree
Showing 32 changed files with 315 additions and 1,926 deletions.
2 changes: 2 additions & 0 deletions .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
/src/mono/mono/metadata/thread* @lateralusX @lambdageek
/src/mono/mono/metadata/w32* @lateralusX @lambdageek

/src/mono/mono/eventpipe @lateralusX @lambdageek

/src/mono/mono/mini @vargaz @lambdageek @SamMonoRT
/src/mono/mono/mini/*cfgdump* @vargaz
/src/mono/mono/mini/*exceptions* @vargaz @BrzVlad
Expand Down
11 changes: 4 additions & 7 deletions src/mono/cmake/config.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,9 @@
/* Host Platform is Darwin */
#cmakedefine HOST_DARWIN 1

/* Host Platform is OSX or Mac Catalyst */
#cmakedefine HOST_OSX 1

/* Host Platform is iOS */
#cmakedefine HOST_IOS 1

Expand Down Expand Up @@ -154,9 +157,6 @@
/* Define to 1 if you have the <sys/sysctl.h> header file. */
#cmakedefine HAVE_SYS_SYSCTL_H 1

/* Define to 1 if you have the <libproc.h> header file. */
#cmakedefine HAVE_LIBPROC_H 1

/* Define to 1 if you have the <sys/prctl.h> header file. */
#cmakedefine HAVE_SYS_PRCTL_H 1

Expand Down Expand Up @@ -399,9 +399,6 @@
/* Define to 1 if you have the `getpwuid_r' function. */
#cmakedefine HAVE_GETPWUID_R 1

/* Define to 1 if you have the `readlink' function. */
#cmakedefine HAVE_READLINK 1

/* Define to 1 if you have the `chmod' function. */
#cmakedefine HAVE_CHMOD 1

Expand Down Expand Up @@ -819,7 +816,7 @@
/* The JIT/AOT targets Mac Catalyst */
#cmakedefine TARGET_MACCAT 1

/* The JIT/AOT targets OSX */
/* The JIT/AOT targets OSX or Mac Catalyst */
#cmakedefine TARGET_OSX 1

/* The JIT/AOT targets Apple platforms */
Expand Down
4 changes: 2 additions & 2 deletions src/mono/cmake/configure.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ ac_check_headers (
sys/types.h sys/stat.h sys/filio.h sys/sockio.h sys/utime.h sys/un.h sys/syscall.h sys/uio.h sys/param.h
sys/prctl.h sys/socket.h sys/utsname.h sys/select.h sys/poll.h sys/wait.h sts/auxv.h sys/resource.h
sys/ioctl.h sys/errno.h sys/sendfile.h sys/statvfs.h sys/statfs.h sys/mman.h sys/mount.h sys/time.h sys/random.h
strings.h stdint.h unistd.h signal.h setjmp.h syslog.h netdb.h utime.h semaphore.h libproc.h alloca.h ucontext.h pwd.h elf.h
strings.h stdint.h unistd.h signal.h setjmp.h syslog.h netdb.h utime.h semaphore.h alloca.h ucontext.h pwd.h elf.h
gnu/lib-names.h netinet/tcp.h netinet/in.h link.h arpa/inet.h unwind.h poll.h wchar.h linux/magic.h
android/legacy_signal_inlines.h execinfo.h pthread.h pthread_np.h net/if.h dirent.h
CommonCrypto/CommonDigest.h dlfcn.h getopt.h pwd.h alloca.h
Expand All @@ -77,7 +77,7 @@ ac_check_headers (
ac_check_funcs (
sigaction kill clock_nanosleep backtrace_symbols mkstemp mmap
getrusage dladdr sysconf getrlimit prctl nl_langinfo
sched_getaffinity sched_setaffinity getpwuid_r readlink chmod lstat getdtablesize ftruncate msync
sched_getaffinity sched_setaffinity getpwuid_r chmod lstat getdtablesize ftruncate msync
getpeername utime utimes openlog closelog atexit popen strerror_r inet_pton inet_aton
shm_open poll getfsstat mremap posix_fadvise vsnprintf sendfile statfs statvfs setpgid system
fork execv execve waitpid localtime_r mkdtemp getrandom execvp strlcpy stpcpy strtok_r rewinddir
Expand Down
267 changes: 263 additions & 4 deletions src/mono/mono/eventpipe/ep-rt-mono.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@
#include <mono/mini/mini-runtime.h>
#include <mono/sgen/sgen-conf.h>
#include <mono/sgen/sgen-tagged-pointer.h>
#include "mono/utils/mono-logger-internals.h"
#include <mono/utils/mono-logger-internals.h>
#include <minipal/getexepath.h>
#include <runtime_version.h>
#include <clretwallmain.h>

Expand Down Expand Up @@ -1123,6 +1124,18 @@ ep_rt_mono_rand_try_get_bytes (
uint8_t *buffer,
size_t buffer_size);

char *
ep_rt_mono_get_cmd_line (bool add_host);

ep_rt_file_handle_t
ep_rt_mono_file_open_write(const ep_char8_t *path);

bool
ep_rt_mono_file_close (ep_rt_file_handle_t handle);

bool
ep_rt_mono_file_write (ep_rt_file_handle_t handle, const uint8_t *buffer, uint32_t numbytes, uint32_t *byteswritten);

EventPipeThread *
ep_rt_mono_thread_get_or_create (void);

Expand Down Expand Up @@ -2069,6 +2082,252 @@ ep_rt_mono_rand_try_get_bytes (
return mono_rand_try_get_bytes (&_ep_rt_mono_rand_provider, (guchar *)buffer, (gssize)buffer_size, error);
}

static GString *
quote_escape_and_append_string (char *src_str, GString *target_str)
{
#ifdef HOST_WIN32
char quote_char = '\"';
char escape_chars[] = "\"\\";
#else
char quote_char = '\'';
char escape_chars[] = "\'\\";
#endif

gboolean need_quote = FALSE;
gboolean need_escape = FALSE;

for (char *pos = src_str; *pos; ++pos) {
if (isspace (*pos))
need_quote = TRUE;
if (strchr (escape_chars, *pos))
need_escape = TRUE;
}

if (need_quote)
target_str = g_string_append_c (target_str, quote_char);

if (need_escape) {
for (char *pos = src_str; *pos; ++pos) {
if (strchr (escape_chars, *pos))
target_str = g_string_append_c (target_str, '\\');
target_str = g_string_append_c (target_str, *pos);
}
} else {
target_str = g_string_append (target_str, src_str);
}

if (need_quote)
target_str = g_string_append_c (target_str, quote_char);

return target_str;
}

char *
ep_rt_mono_get_managed_cmd_line ()
{
MONO_REQ_GC_NEUTRAL_MODE;

int argc = mono_runtime_get_main_args_argc_raw ();
if (argc == 0)
return NULL;

// managed cmdline -> native host + managed argv (which includes the entrypoint assembly)
size_t total_size = 0;
char *host_path = NULL;
char **argv = mono_runtime_get_main_args_argv_raw ();
GString *cmd_line = NULL;

host_path = minipal_getexepath();

if (host_path)
// quote + string + quote
total_size += strlen (host_path) + 2;

for (int i = 0; i < argc; ++i) {
if (argv [i]) {
if (total_size > 0) {
// add space
total_size++;
}
// quote + string + quote
total_size += strlen (argv [i]) + 2;
}
}

// String will grow if needed, so not over allocating
// to handle case of escaped characters in arguments, if
// that happens string will automatically grow.
cmd_line = g_string_sized_new (total_size + 1);

if (cmd_line) {
if (host_path)
cmd_line = quote_escape_and_append_string (host_path, cmd_line);

for (int i = 0; i < argc; ++i) {
if (argv [i]) {
if (cmd_line->len > 0) {
// add space
cmd_line = g_string_append_c (cmd_line, ' ');
}
cmd_line = quote_escape_and_append_string (argv [i], cmd_line);
}
}
}

g_free (host_path);

return cmd_line ? g_string_free (cmd_line, FALSE) : NULL;
}

char *
ep_rt_mono_get_os_cmd_line ()
{
MONO_REQ_GC_NEUTRAL_MODE;

// we only return the native host here since getting the full commandline is complicated and
// it's not super important to have the correct value since it'll only be used during startup
// until we have the managed commandline
return minipal_getexepath();
}

#ifdef HOST_WIN32

ep_rt_file_handle_t
ep_rt_mono_file_open_write(const ep_char8_t *path)
{
if (!path)
return INVALID_HANDLE_VALUE;

ep_char16_t *path_utf16 = ep_rt_utf8_to_utf16_string (path, -1);

if (!path_utf16)
return INVALID_HANDLE_VALUE;

ep_rt_file_handle_t res;
MONO_ENTER_GC_SAFE;
res = (ep_rt_file_handle_t)CreateFileW (path_utf16, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
MONO_EXIT_GC_SAFE;
ep_rt_utf16_string_free (path_utf16);

return res;
}

bool
ep_rt_mono_file_close (ep_rt_file_handle_t handle)
{
bool res;
MONO_ENTER_GC_SAFE;
res = CloseHandle (handle);
MONO_EXIT_GC_SAFE;
return res;
}

static void
win32_io_interrupt_handler (void* ignored)
{
}

bool
ep_rt_mono_file_write (ep_rt_file_handle_t handle, const uint8_t *buffer, uint32_t numbytes, uint32_t *byteswritten)
{
bool res;
MonoThreadInfo *info = mono_thread_info_current ();
gboolean alerted = FALSE;

if (info) {
mono_thread_info_install_interrupt (win32_io_interrupt_handler, NULL, &alerted);
if (alerted) {
return FALSE;
}
mono_win32_enter_blocking_io_call (info, handle);
}

MONO_ENTER_GC_SAFE;
if (info && mono_thread_info_is_interrupt_state (info)) {
res = FALSE;
} else {
res = WriteFile (handle, buffer, numbytes, (PDWORD)byteswritten, NULL) ? TRUE : FALSE;
}
MONO_EXIT_GC_SAFE;

if (info) {
mono_win32_leave_blocking_io_call (info, handle);
mono_thread_info_uninstall_interrupt (&alerted);
}

return res;
}

#else

#include <fcntl.h>
#include <unistd.h>

ep_rt_file_handle_t
ep_rt_mono_file_open_write(const ep_char8_t *path)
{
int fd;
mode_t perms = 0666;

if (!path)
return INVALID_HANDLE_VALUE;

MONO_ENTER_GC_SAFE;
fd = creat (path, perms);
MONO_EXIT_GC_SAFE;

if (fd == -1)
return INVALID_HANDLE_VALUE;

return (ep_rt_file_handle_t)(ptrdiff_t)fd;
}

bool
ep_rt_mono_file_close (ep_rt_file_handle_t handle)
{
int fd = (int)(ptrdiff_t)handle;

MONO_ENTER_GC_SAFE;
close (fd);
MONO_EXIT_GC_SAFE;

return TRUE;
}

bool
ep_rt_mono_file_write (ep_rt_file_handle_t handle, const uint8_t *buffer, uint32_t numbytes, uint32_t *byteswritten)
{
MONO_REQ_GC_UNSAFE_MODE;

int fd = (int)(ptrdiff_t)handle;
uint32_t ret;
MonoThreadInfo *info = mono_thread_info_current ();

if (byteswritten != NULL)
*byteswritten = 0;

do {
MONO_ENTER_GC_SAFE;
ret = write (fd, buffer, numbytes);
MONO_EXIT_GC_SAFE;
} while (ret == -1 && errno == EINTR &&
!mono_thread_info_is_interrupt_state (info));

if (ret == -1) {
if (errno == EINTR)
ret = 0;
else
return FALSE;
}

if (byteswritten != NULL)
*byteswritten = ret;

return TRUE;
}

#endif // HOST_WIN32

EventPipeThread *
ep_rt_mono_thread_get_or_create (void)
{
Expand Down Expand Up @@ -2224,7 +2483,7 @@ static const int64_t SECS_TO_NS = 1000000000;
static const int64_t MSECS_TO_MIS = 1000;

/* clock_gettime () is found by configure on Apple builds, but its only present from ios 10, macos 10.12, tvos 10 and watchos 3 */
#if defined (HAVE_CLOCK_MONOTONIC) && (defined(TARGET_IOS) || defined(TARGET_OSX) || defined(TARGET_WATCHOS) || defined(TARGET_TVOS))
#if defined (HAVE_CLOCK_MONOTONIC) && (defined(HOST_IOS) || defined(HOST_OSX) || defined(HOST_WATCHOS) || defined(HOST_TVOS))
#undef HAVE_CLOCK_MONOTONIC
#endif

Expand Down Expand Up @@ -2375,15 +2634,15 @@ ep_rt_mono_system_timestamp_get (void)

#ifndef HOST_WIN32
#if defined(__APPLE__)
#if defined (TARGET_OSX)
#if defined (HOST_OSX)
G_BEGIN_DECLS
gchar ***_NSGetEnviron(void);
G_END_DECLS
#define environ (*_NSGetEnviron())
#else
static char *_ep_rt_mono_environ[1] = { NULL };
#define environ _ep_rt_mono_environ
#endif /* defined (TARGET_OSX) */
#endif /* defined (HOST_OSX) */
#else
G_BEGIN_DECLS
extern char **environ;
Expand Down
Loading

0 comments on commit e82c20a

Please sign in to comment.