Flush iochannel before shutting it down.
This commit is contained in:
parent
53ee79f088
commit
d16c706645
1
moo/TODO
1
moo/TODO
@ -4,6 +4,7 @@ Editor
|
||||
1. Color settings!!!
|
||||
2. Default lang, for ggap.
|
||||
3. See what can be done in the absence of xml.
|
||||
4. Make messages in xml parser include file name.
|
||||
|
||||
|
||||
Terminal
|
||||
|
@ -605,6 +605,16 @@ static gboolean do_write (MooEdit *edit,
|
||||
}
|
||||
while (gtk_text_iter_forward_line (&line_start));
|
||||
|
||||
/* glib #320668 */
|
||||
status = g_io_channel_flush (file, error);
|
||||
|
||||
if (status != G_IO_STATUS_NORMAL)
|
||||
{
|
||||
g_io_channel_shutdown (file, FALSE, NULL);
|
||||
g_io_channel_unref (file);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
status = g_io_channel_shutdown (file, TRUE, error);
|
||||
|
||||
if (status != G_IO_STATUS_NORMAL)
|
||||
|
@ -1,361 +0,0 @@
|
||||
/*
|
||||
* moohandlewatch.c
|
||||
*
|
||||
* Copyright (C) 2004-2005 by Yevgen Muntyan <muntyan@math.tamu.edu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* See COPYING file that comes with this distribution.
|
||||
*/
|
||||
|
||||
#include "mooutils/moohandlewatch.h"
|
||||
|
||||
|
||||
#ifndef __WIN32__
|
||||
static gboolean SetEvent (G_GNUC_UNUSED HANDLE handle)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
static HANDLE CreateEvent (G_GNUC_UNUSED gpointer sec_attrs,
|
||||
G_GNUC_UNUSED gboolean manual_reset,
|
||||
G_GNUC_UNUSED gboolean initial_state,
|
||||
G_GNUC_UNUSED const char *name)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
static int GetLastError (void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static char *g_win32_error_message (G_GNUC_UNUSED int err)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
static void CloseHandle (G_GNUC_UNUSED HANDLE handle)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
typedef enum {
|
||||
REQUEST_ADD,
|
||||
REQUEST_REMOVE,
|
||||
REQUEST_CONTINUE,
|
||||
REQUEST_DIE
|
||||
} RequestCode;
|
||||
|
||||
typedef struct {
|
||||
RequestCode code;
|
||||
HANDLE handle;
|
||||
HANDLE event;
|
||||
GAsyncQueue *answer;
|
||||
} Request;
|
||||
|
||||
|
||||
typedef struct {
|
||||
guint handle_id;
|
||||
HANDLE handle;
|
||||
MooHandleFunc func;
|
||||
gpointer user_data;
|
||||
} HandleInfo;
|
||||
|
||||
typedef struct {
|
||||
GSource source;
|
||||
GPollFD thread_event;
|
||||
Request *request;
|
||||
GAsyncQueue *events;
|
||||
GSList *handles; /* HandleInfo* */
|
||||
} HandleWatch;
|
||||
|
||||
|
||||
static gboolean watch_thread_start (HANDLE event,
|
||||
Request *request,
|
||||
GAsyncQueue *events);
|
||||
|
||||
static void watch_resume_thread (HandleWatch *watch);
|
||||
static void watch_kill_thread (HandleWatch *watch);
|
||||
static gboolean watch_do_event (HandleWatch *watch,
|
||||
gpointer event);
|
||||
|
||||
static gboolean handle_watch_prepare (G_GNUC_UNUSED GSource *source,
|
||||
gint *timeout_)
|
||||
{
|
||||
*timeout_ = -1;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
static gboolean handle_watch_check (GSource *source)
|
||||
{
|
||||
HandleWatch *watch = (HandleWatch*) source;
|
||||
return watch->thread_event.revents != 0;
|
||||
}
|
||||
|
||||
|
||||
static gboolean handle_watch_dispatch (G_GNUC_UNUSED GSource *source,
|
||||
GSourceFunc callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
return callback (user_data);
|
||||
}
|
||||
|
||||
|
||||
static void handle_watch_finalize (G_GNUC_UNUSED GSource *source)
|
||||
{
|
||||
g_critical ("Oh no, I'm finalized!");
|
||||
}
|
||||
|
||||
|
||||
static gboolean handle_watch_callback (HandleWatch *watch)
|
||||
{
|
||||
if (watch->thread_event.revents & (G_IO_HUP | G_IO_ERR))
|
||||
{
|
||||
g_critical ("Oh no, error!");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
while (g_async_queue_length (watch->events))
|
||||
{
|
||||
gpointer event = g_async_queue_pop (watch->events);
|
||||
if (!watch_do_event (watch, event))
|
||||
watch_kill_thread (watch);
|
||||
}
|
||||
|
||||
watch_resume_thread (watch);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
static HandleWatch *handle_watch_get (gboolean create)
|
||||
{
|
||||
static HandleWatch *instance = NULL;
|
||||
GSource *source;
|
||||
|
||||
static GSourceFuncs handle_watch_funcs = {
|
||||
handle_watch_prepare,
|
||||
handle_watch_check,
|
||||
handle_watch_dispatch,
|
||||
handle_watch_finalize,
|
||||
NULL, NULL
|
||||
};
|
||||
|
||||
if (!create || instance != NULL)
|
||||
return instance;
|
||||
|
||||
source = g_source_new (&handle_watch_funcs,
|
||||
sizeof (HandleWatch));
|
||||
g_return_val_if_fail (source != NULL, NULL);
|
||||
|
||||
g_source_set_callback (source,
|
||||
(GSourceFunc) handle_watch_callback,
|
||||
source, NULL);
|
||||
|
||||
instance = (HandleWatch*)source;
|
||||
instance->handles = NULL;
|
||||
instance->events = g_async_queue_new ();
|
||||
|
||||
instance->thread_event.fd = (int) CreateEvent (NULL, FALSE, FALSE, NULL);
|
||||
instance->thread_event.events = TRUE;
|
||||
|
||||
if (!instance->thread_event.fd)
|
||||
{
|
||||
int err = GetLastError ();
|
||||
char *msg = g_win32_error_message (err);
|
||||
g_critical ("%s: CreateEvent failed: %s", G_STRLOC, msg);
|
||||
g_free (msg);
|
||||
goto error;
|
||||
}
|
||||
|
||||
instance->request = g_new0 (Request, 1);
|
||||
instance->request->answer = g_async_queue_new ();
|
||||
instance->request->event = CreateEvent (NULL, FALSE, FALSE, NULL);
|
||||
|
||||
if (!instance->request->event)
|
||||
{
|
||||
int err = GetLastError ();
|
||||
char *msg = g_win32_error_message (err);
|
||||
g_critical ("%s: CreateEvent failed: %s", G_STRLOC, msg);
|
||||
g_free (msg);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!watch_thread_start ((HANDLE) instance->thread_event.fd,
|
||||
instance->request, instance->events))
|
||||
{
|
||||
g_critical ("%s: could not start thread", G_STRLOC);
|
||||
goto error;
|
||||
}
|
||||
|
||||
g_source_add_poll (source, &instance->thread_event);
|
||||
g_source_attach (source, NULL);
|
||||
return instance;
|
||||
|
||||
error:
|
||||
if (instance->thread_event.fd)
|
||||
CloseHandle ((HANDLE) instance->thread_event.fd);
|
||||
instance->thread_event.fd = 0;
|
||||
|
||||
if (instance->request)
|
||||
{
|
||||
if (instance->request->answer)
|
||||
g_async_queue_unref (instance->request->answer);
|
||||
if (instance->request->event)
|
||||
CloseHandle (instance->request->event);
|
||||
g_free (instance->request);
|
||||
instance->request = NULL;
|
||||
}
|
||||
|
||||
if (instance->events)
|
||||
g_async_queue_unref (instance->events);
|
||||
instance->events = NULL;
|
||||
|
||||
instance = NULL;
|
||||
g_source_destroy (source);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
guint moo_handle_watch_add (HANDLE handle,
|
||||
MooHandleFunc func,
|
||||
gpointer user_data)
|
||||
{
|
||||
Request *request;
|
||||
gpointer result;
|
||||
HandleWatch *watch;
|
||||
|
||||
watch = handle_watch_get (TRUE);
|
||||
g_return_val_if_fail (watch != NULL, 0);
|
||||
|
||||
request = watch->request;
|
||||
|
||||
request->code = REQUEST_ADD;
|
||||
request->handle = handle;
|
||||
|
||||
if (!SetEvent (request->event))
|
||||
{
|
||||
int err = GetLastError ();
|
||||
char *msg = g_win32_error_message (err);
|
||||
g_critical ("%s: SetEvent failed: %s", G_STRLOC, msg);
|
||||
g_free (msg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
result = g_async_queue_pop (request->answer);
|
||||
|
||||
if (result)
|
||||
{
|
||||
HandleInfo *info = g_new (HandleInfo, 1);
|
||||
|
||||
info->handle_id = GPOINTER_TO_UINT (result);
|
||||
info->handle = handle;
|
||||
info->func = func;
|
||||
info->user_data = user_data;
|
||||
|
||||
watch->handles = g_slist_prepend (watch->handles, info);
|
||||
|
||||
g_message ("%s: added handle, id %d",
|
||||
G_STRLOC, info->handle_id);
|
||||
|
||||
return info->handle_id;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_warning ("%s: adding handle failed", G_STRLOC);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int cmp_handle (HandleInfo *info,
|
||||
HANDLE handle)
|
||||
{
|
||||
return info->handle != handle;
|
||||
}
|
||||
|
||||
guint moo_handle_watch_remove_handle (HANDLE handle)
|
||||
{
|
||||
Request *request;
|
||||
gpointer result;
|
||||
HandleWatch *watch;
|
||||
GSList *link;
|
||||
HandleInfo *info;
|
||||
|
||||
watch = handle_watch_get (FALSE);
|
||||
g_return_val_if_fail (watch != NULL, 0);
|
||||
|
||||
link = g_slist_find_custom (watch->handles, handle,
|
||||
(GCompareFunc) cmp_handle);
|
||||
g_return_val_if_fail (link != NULL, 0);
|
||||
|
||||
info = link->data;
|
||||
request = watch->request;
|
||||
|
||||
request->code = REQUEST_REMOVE;
|
||||
request->handle = handle;
|
||||
|
||||
if (!SetEvent (request->event))
|
||||
{
|
||||
int err = GetLastError ();
|
||||
char *msg = g_win32_error_message (err);
|
||||
g_critical ("%s: SetEvent failed: %s", G_STRLOC, msg);
|
||||
g_free (msg);
|
||||
result = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = g_async_queue_pop (request->answer);
|
||||
|
||||
if (result)
|
||||
{
|
||||
if (info->handle_id != GPOINTER_TO_UINT (result) ||
|
||||
info->handle != handle)
|
||||
{
|
||||
g_critical ("%s: oops", G_STRLOC);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_message ("%s: removed handle id %d",
|
||||
G_STRLOC, info->handle_id);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
g_warning ("%s: removing handle id %d failed",
|
||||
G_STRLOC, info->handle_id);
|
||||
}
|
||||
}
|
||||
|
||||
g_free (link->data);
|
||||
watch->handles = g_slist_delete_link (watch->handles, link);
|
||||
|
||||
return GPOINTER_TO_UINT (result);
|
||||
}
|
||||
|
||||
|
||||
static int cmp_handle_id (HandleInfo *info,
|
||||
gpointer id)
|
||||
{
|
||||
return info->handle_id != GPOINTER_TO_UINT (id);
|
||||
}
|
||||
|
||||
guint moo_handle_watch_remove (guint handle_id)
|
||||
{
|
||||
HandleWatch *watch;
|
||||
GSList *link;
|
||||
HandleInfo *info;
|
||||
|
||||
watch = handle_watch_get (FALSE);
|
||||
g_return_val_if_fail (watch != NULL, 0);
|
||||
|
||||
link = g_slist_find_custom (watch->handles,
|
||||
GUINT_TO_POINTER (handle_id),
|
||||
(GCompareFunc) cmp_handle_id);
|
||||
g_return_val_if_fail (link != NULL, 0);
|
||||
|
||||
info = link->data;
|
||||
|
||||
return moo_handle_watch_remove_handle (info->handle);
|
||||
}
|
@ -1,151 +0,0 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4; coding: utf-8 -*-
|
||||
* moohandlewatch.h
|
||||
*
|
||||
* Copyright (C) 2004-2005 by Yevgen Muntyan <muntyan@math.tamu.edu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* See COPYING file that comes with this distribution.
|
||||
*/
|
||||
|
||||
/* Win32 HANDLE monitor. It's a GSource wrapping WaitForMultipleObjects,
|
||||
intended to workaround limitation of 64 handles per GMainContext. */
|
||||
|
||||
#ifndef __MOO_HANDLE_WATCH_H__
|
||||
#define __MOO_HANDLE_WATCH_H__
|
||||
|
||||
#include <glib.h>
|
||||
#ifdef __WIN32__
|
||||
#include <windows.h>
|
||||
#else
|
||||
typedef gpointer HANDLE;
|
||||
#endif
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
||||
#define MOO_HANDLE_WATCH_ERROR (moo_handle_watch_error_quark ())
|
||||
|
||||
typedef enum {
|
||||
MOO_HANDLE_WATCH_ERROR_FAILED,
|
||||
MOO_HANDLE_WATCH_ERROR_NOT_IMPLEMENTED
|
||||
} MooHandleWatchError;
|
||||
|
||||
typedef enum {
|
||||
MOO_HANDLE_SIGNALLED,
|
||||
MOO_HANDLE_ERROR
|
||||
} MooHandleCondition;
|
||||
|
||||
typedef gboolean (*MooHandleFunc) (HANDLE handle,
|
||||
MooHandleCondition condition,
|
||||
gpointer user_data);
|
||||
|
||||
GQuark moo_handle_watch_error_quark (void);
|
||||
|
||||
guint moo_handle_watch_add (HANDLE handle,
|
||||
MooHandleFunc func,
|
||||
gpointer user_data);
|
||||
|
||||
guint moo_handle_watch_remove_handle (HANDLE handle);
|
||||
guint moo_handle_watch_remove (guint handle_id);
|
||||
|
||||
|
||||
// #define MOO_TYPE_HANDLE_WATCH (moo_handle_watch_get_type ())
|
||||
// #define MOO_HANDLE_WATCH(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), MOO_TYPE_HANDLE_WATCH, MooHandleWatch))
|
||||
// #define MOO_HANDLE_WATCH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MOO_TYPE_HANDLE_WATCH, MooHandleWatchClass))
|
||||
// #define MOO_IS_HANDLE_WATCH(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), MOO_TYPE_HANDLE_WATCH))
|
||||
// #define MOO_IS_HANDLE_WATCH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MOO_TYPE_HANDLE_WATCH))
|
||||
// #define MOO_HANDLE_WATCH_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MOO_TYPE_HANDLE_WATCH, MooHandleWatchClass))
|
||||
//
|
||||
// #define MOO_TYPE_HANDLE_WATCH_EVENT_CODE (moo_handle_watch_event_code_get_type ())
|
||||
// #define MOO_TYPE_HANDLE_WATCH_METHOD (moo_handle_watch_method_get_type ())
|
||||
//
|
||||
// typedef enum {
|
||||
// MOO_HANDLE_WATCH_STAT,
|
||||
// MOO_HANDLE_WATCH_FAM,
|
||||
// MOO_HANDLE_WATCH_WIN32
|
||||
// } MooHandleWatchMethod;
|
||||
//
|
||||
// /* Stripped FAMEventCode enumeration */
|
||||
// typedef enum {
|
||||
// MOO_HANDLE_WATCH_CHANGED = 1,
|
||||
// MOO_HANDLE_WATCH_DELETED = 2,
|
||||
// MOO_HANDLE_WATCH_CREATED = 3,
|
||||
// MOO_HANDLE_WATCH_MOVED = 4,
|
||||
// } MooHandleWatchEventCode;
|
||||
//
|
||||
// /* The structure has the same meaning as the FAMEvent
|
||||
// (it is a simple copy of FAMEvent structure when
|
||||
// FAM is used). In the case when stat() is used, when
|
||||
// directory content is changed, MooHandleWatch does not
|
||||
// try to learn what happened, and just emits CHANGED
|
||||
// event with filename set to directory name.
|
||||
// */
|
||||
// struct _MooHandleWatchEvent {
|
||||
// MooHandleWatchEventCode code; /* FAMEventCode */
|
||||
// int monitor_id; /* FAMRequest */
|
||||
// char *filename;
|
||||
// gpointer data;
|
||||
// };
|
||||
//
|
||||
// typedef struct _MooHandleWatch MooHandleWatch;
|
||||
// typedef struct _MooHandleWatchPrivate MooHandleWatchPrivate;
|
||||
// typedef struct _MooHandleWatchClass MooHandleWatchClass;
|
||||
// typedef struct _MooHandleWatchEvent MooHandleWatchEvent;
|
||||
//
|
||||
// struct _MooHandleWatch
|
||||
// {
|
||||
// GObject parent;
|
||||
// MooHandleWatchPrivate *priv;
|
||||
// };
|
||||
//
|
||||
// struct _MooHandleWatchClass
|
||||
// {
|
||||
// GObjectClass parent_class;
|
||||
//
|
||||
// void (*event) (MooHandleWatch *watch,
|
||||
// MooHandleWatchEvent *event);
|
||||
// void (*error) (MooHandleWatch *watch,
|
||||
// GError *error);
|
||||
// };
|
||||
//
|
||||
// GType moo_handle_watch_get_type (void) G_GNUC_CONST;
|
||||
// GType moo_handle_watch_event_code_get_type (void) G_GNUC_CONST;
|
||||
// GType moo_handle_watch_method_get_type (void) G_GNUC_CONST;
|
||||
//
|
||||
// /* FAMOpen */
|
||||
// MooHandleWatch *moo_handle_watch_new (GError **error);
|
||||
//
|
||||
// /* FAMClose */
|
||||
// gboolean moo_handle_watch_close (MooHandleWatch *watch,
|
||||
// GError **error);
|
||||
//
|
||||
// /* FAMMonitorDirectory, FAMMonitorFile */
|
||||
// gboolean moo_handle_watch_monitor_directory (MooHandleWatch *watch,
|
||||
// const char *filename,
|
||||
// gpointer data,
|
||||
// int *monitor_id,
|
||||
// GError **error);
|
||||
// gboolean moo_handle_watch_monitor_file (MooHandleWatch *watch,
|
||||
// const char *filename,
|
||||
// gpointer data,
|
||||
// int *monitor_id,
|
||||
// GError **error);
|
||||
//
|
||||
// /* FAMSuspendMonitor, FAMResumeMonitor, FAMCancelMonitor */
|
||||
// void moo_handle_watch_suspend_monitor (MooHandleWatch *watch,
|
||||
// int monitor_id);
|
||||
// void moo_handle_watch_resume_monitor (MooHandleWatch *watch,
|
||||
// int monitor_id);
|
||||
// void moo_handle_watch_cancel_monitor (MooHandleWatch *watch,
|
||||
// int monitor_id);
|
||||
//
|
||||
// MooHandleWatchMethod moo_handle_watch_get_method (MooHandleWatch *watch);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __MOO_HANDLE_WATCH_H__ */
|
@ -1,22 +0,0 @@
|
||||
/*
|
||||
* mooutils/moolog.c
|
||||
*
|
||||
* Copyright (C) 2004-2005 by Yevgen Muntyan <muntyan@math.tamu.edu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* See COPYING file that comes with this distribution.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#ifdef __WIN32__
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#endif /* __WIN32__ */
|
||||
#include "mooutils/moolog.h"
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
|
@ -1,26 +0,0 @@
|
||||
/*
|
||||
* mooutils/moolog.h
|
||||
*
|
||||
* Copyright (C) 2004-2005 by Yevgen Muntyan <muntyan@math.tamu.edu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* See COPYING file that comes with this distribution.
|
||||
*/
|
||||
|
||||
#ifndef DEBUG_H
|
||||
#define DEBUG_H
|
||||
|
||||
#include <glib/gmessages.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* DEBUG_H */
|
@ -154,12 +154,16 @@ moo_save_file_utf8 (const char *name,
|
||||
|
||||
if (status != G_IO_STATUS_NORMAL || bytes_written != real_len)
|
||||
{
|
||||
g_io_channel_shutdown (file, TRUE, NULL);
|
||||
/* glib #320668 */
|
||||
g_io_channel_flush (file, NULL);
|
||||
g_io_channel_shutdown (file, FALSE, NULL);
|
||||
g_io_channel_unref (file);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_io_channel_shutdown (file, TRUE, NULL);
|
||||
/* glib #320668 */
|
||||
g_io_channel_flush (file, NULL);
|
||||
g_io_channel_shutdown (file, FALSE, NULL);
|
||||
g_io_channel_unref (file);
|
||||
return TRUE;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user