diff --git a/codegen/valaccodemethodcallmodule.vala b/codegen/valaccodemethodcallmodule.vala
index 8fc87db..4cf641d 100644
--- a/codegen/valaccodemethodcallmodule.vala
+++ b/codegen/valaccodemethodcallmodule.vala
@@ -53,7 +53,7 @@ internal class Vala.CCodeMethodCallModule : CCodeAssignmentModule {
 		} else if (itype is SignalType) {
 			var sig_type = (SignalType) itype;
 			if (ma != null && ma.inner is BaseAccess && sig_type.signal_symbol.is_virtual) {
-				m = sig_type.signal_symbol.get_method_handler ();
+				m = sig_type.signal_symbol.default_handler;
 			} else {
 				ccall = (CCodeFunctionCall) expr.call.ccodenode;
 			}
diff --git a/codegen/valaccodemethodmodule.vala b/codegen/valaccodemethodmodule.vala
index d76fbce..d8342a6 100644
--- a/codegen/valaccodemethodmodule.vala
+++ b/codegen/valaccodemethodmodule.vala
@@ -599,7 +599,12 @@ internal class Vala.CCodeMethodModule : CCodeStructModule {
 			}
 		}
 
-		if ((m.is_abstract || m.is_virtual) && !m.coroutine) {
+		if ((m.is_abstract || m.is_virtual) && !m.coroutine &&
+		/* If the method is a signal handler, the declaration
+		 * is not needed. -- the name should be reserved for the
+		 * emitter! */
+			    m.signal_reference == null) {
+
 			cparam_map = new HashMap<int,CCodeFormalParameter> (direct_hash, direct_equal);
 			var carg_map = new HashMap<int,CCodeExpression> (direct_hash, direct_equal);
 
diff --git a/codegen/valagsignalmodule.vala b/codegen/valagsignalmodule.vala
index f4ed94d..a739d10 100644
--- a/codegen/valagsignalmodule.vala
+++ b/codegen/valagsignalmodule.vala
@@ -171,6 +171,34 @@ internal class Vala.GSignalModule : GObjectModule {
 		}
 
 		generate_marshaller (sig.get_parameters (), sig.return_type);
+
+		if(sig.has_emitter) {
+			var emitter = new CCodeFunction ("%s_%s".printf(
+			       cl.get_lower_case_cname(null), sig.get_cname ()));
+			int n_params = 0;
+			emitter.add_parameter (
+			        new CCodeFormalParameter ("*self", cl.get_cname ()));
+			foreach (FormalParameter p in sig.get_parameters ()) {
+				emitter.add_parameter (new CCodeFormalParameter (p.name, get_value_type_name_from_parameter (p)));
+				n_params++;
+				if (p.parameter_type.is_array ()) {
+					emitter.add_parameter (new CCodeFormalParameter ("%s_length".printf (p.name), "gint"));
+					n_params++;
+				}
+			}
+			var vblock = new CCodeBlock();
+
+			emitter.line = function.line;
+			bool visible = !sig.is_internal_symbol ();
+			if (visible) {
+				header_declarations.add_type_member_declaration (emitter.copy ());
+			} else {
+				emitter.modifiers |= CCodeModifiers.STATIC;
+				source_declarations.add_type_member_declaration (emitter.copy ());
+			}
+			emitter.block = vblock;
+			source_type_member_definition.append (emitter);
+		}
 	}
 
 	public override void generate_marshaller (Gee.List<FormalParameter> params, DataType return_type, bool dbus = false) {
@@ -355,10 +383,19 @@ internal class Vala.GSignalModule : GObjectModule {
 
 	public override CCodeFunctionCall get_signal_creation (Signal sig, TypeSymbol type) {	
 		var csignew = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_new"));
+		var cl = sig.parent_symbol as Class;
 		csignew.add_argument (new CCodeConstant ("\"%s\"".printf (sig.get_cname ())));
 		csignew.add_argument (new CCodeIdentifier (type.get_type_id ()));
-		csignew.add_argument (new CCodeConstant ("G_SIGNAL_RUN_LAST"));
-		csignew.add_argument (new CCodeConstant ("0"));
+		csignew.add_argument (new CCodeConstant (get_signal_stage_cname(sig.stage)));
+		if(sig.default_handler == null) {
+			csignew.add_argument (new CCodeConstant ("0"));
+		} else {
+			var struct_offset = new CCodeFunctionCall (new CCodeIdentifier ("G_STRUCT_OFFSET"));
+			struct_offset.add_argument (new CCodeIdentifier("%sClass".printf (cl.get_cname ())));
+			struct_offset.add_argument (new
+			CCodeIdentifier(sig.default_handler.vfunc_name));
+			csignew.add_argument (struct_offset);
+		}
 		csignew.add_argument (new CCodeConstant ("NULL"));
 		csignew.add_argument (new CCodeConstant ("NULL"));
 
@@ -608,7 +645,7 @@ internal class Vala.GSignalModule : GObjectModule {
 			var cl = (TypeSymbol) sig.parent_symbol;
 			
 			if (expr.inner is BaseAccess && sig.is_virtual) {
-				var m = sig.get_method_handler ();
+				var m = sig.default_handler;
 				var base_class = (Class) m.parent_symbol;
 				var vcast = new CCodeFunctionCall (new CCodeIdentifier ("%s_CLASS".printf (base_class.get_upper_case_cname (null))));
 				vcast.add_argument (new CCodeIdentifier ("%s_parent_class".printf (current_class.get_lower_case_cname (null))));
@@ -790,5 +827,20 @@ internal class Vala.GSignalModule : GObjectModule {
 
 		expr.ccodenode = ccall;
 	}
+	private static string get_signal_stage_cname (SignalStage stage) {
+		switch(stage) {
+			case SignalStage.RUN_FIRST:
+				return "G_SIGNAL_RUN_FIRST";
+			case SignalStage.RUN_LAST:
+				return "G_SIGNAL_RUN_LAST";
+			case SignalStage.RUN_CLEANUP:
+				return "G_SIGNAL_RUN_CLEANUP";
+			default:
+				/*'cause only three possible stages are supported
+				 * by GLib. N_RECURSE, DETAILED ACTION, NO_HOOKS 
+				 * are not invocation stages.*/
+				assert_not_reached();
+		}
+	}
 }
 
diff --git a/codegen/valagtypemodule.vala b/codegen/valagtypemodule.vala
index e5bf70e..14d2934 100644
--- a/codegen/valagtypemodule.vala
+++ b/codegen/valagtypemodule.vala
@@ -1140,6 +1140,16 @@ internal class Vala.GTypeModule : GErrorModule {
 			init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ccast, m.base_method.vfunc_name), new CCodeIdentifier (m.get_real_cname ()))));
 		}
 
+		/* connect default signal handlers */
+		foreach (Signal sig in cl.get_signals ()) {
+			if (sig.default_handler == null) {
+				continue;
+			}
+			var ccast = new CCodeFunctionCall (new CCodeIdentifier ("%s_CLASS".printf (cl.get_upper_case_cname (null))));
+			ccast.add_argument (new CCodeIdentifier ("klass"));
+			init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ccast, sig.default_handler.vfunc_name), new CCodeIdentifier (sig.default_handler.get_real_cname ()))));
+		}
+
 		/* connect overridden properties */
 		foreach (Property prop in cl.get_properties ()) {
 			if (prop.base_property == null) {
diff --git a/vala/valamemberaccess.vala b/vala/valamemberaccess.vala
index 3ce7399..5183f04 100644
--- a/vala/valamemberaccess.vala
+++ b/vala/valamemberaccess.vala
@@ -400,6 +400,16 @@ public class Vala.MemberAccess : Expression {
 		}
 
 		var member = symbol_reference;
+		if(member is Method) {
+			var m = member as Method;
+			/*If the member is actually a overriden
+			 * default signal handler, we don't want to
+			 * access this member. Rather we want to access
+			 * the signal.*/
+			if(m.signal_reference != null) {
+				member = m.signal_reference;
+			}
+		}
 		var access = SymbolAccessibility.PUBLIC;
 		bool instance = false;
 		bool klass = false;
diff --git a/vala/valamethod.vala b/vala/valamethod.vala
index 5fa7dd0..ec4e941 100644
--- a/vala/valamethod.vala
+++ b/vala/valamethod.vala
@@ -149,6 +149,21 @@ public class Vala.Method : Member {
 		}
 	}
 
+	/**
+	 * If the function is an anonymous virtual function created
+	 * for the default Signal handler, this member points to the
+	 * owner signal
+	 * */
+	public weak Signal? signal_reference {
+		get {
+			find_base_methods ();
+			return _signal_reference;
+		}
+		set {
+			_signal_reference = value;
+		}
+	}
+
 	public bool entry_point { get; private set; }
 
 	/**
@@ -200,8 +215,6 @@ public class Vala.Method : Member {
 	 */
 	public bool has_construct_function { get; set; default = true; }
 
-	public weak Signal signal_reference { get; set; }
-
 	public bool coroutine { get; set; }
 
 	private Gee.List<FormalParameter> parameters = new ArrayList<FormalParameter> ();
@@ -214,6 +227,7 @@ public class Vala.Method : Member {
 	private Block _body;
 
 	private weak Method _base_method;
+	private weak Signal _signal_reference;
 	private Method _base_interface_method;
 	private bool base_methods_valid;
 
@@ -593,7 +607,7 @@ public class Vala.Method : Member {
 		} else if (sym is Signal) {
 			var sig = (Signal) sym;
 			if (sig.is_virtual) {
-				var base_method = sig.get_method_handler ();
+				var base_method = sig.default_handler;
 				string invalid_match;
 				if (!compatible (base_method, out invalid_match)) {
 					error = true;
@@ -602,6 +616,8 @@ public class Vala.Method : Member {
 				}
 
 				_base_method = base_method;
+				signal_reference = sig;
+
 				return;
 			}
 		}
diff --git a/vala/valaparser.vala b/vala/valaparser.vala
index 88dacd5..93e5cbf 100644
--- a/vala/valaparser.vala
+++ b/vala/valaparser.vala
@@ -2390,7 +2390,10 @@ public class Vala.Parser : CodeVisitor {
 			} while (accept (TokenType.COMMA));
 		}
 		expect (TokenType.CLOSE_PARENS);
-		expect (TokenType.SEMICOLON);
+		if (!accept (TokenType.SEMICOLON)) {
+			sig.body = parse_block ();
+		}
+
 		return sig;
 	}
 
diff --git a/vala/valasignal.vala b/vala/valasignal.vala
index 9b85e89..e0ca86c 100644
--- a/vala/valasignal.vala
+++ b/vala/valasignal.vala
@@ -38,6 +38,16 @@ public class Vala.Signal : Member, Lockable {
 		}
 	}
 
+	public Block body {
+		get { return _body; }
+		set {
+			_body = value;
+			if (_body != null) {
+				_body.owner = scope;
+			}
+		}
+	}
+
 	/**
 	 * Specifies whether this signal has an emitter wrapper function.
 	 */
@@ -48,8 +58,22 @@ public class Vala.Signal : Member, Lockable {
 	 */
 	public bool is_virtual { get; set; }
 
+	/**
+	 * The defatul signal handler's invocation stage.
+	 * Refer to GObject documentation on GSignalFlags
+	 **/
+	public SignalStage stage {
+		get;
+		private set;
+		default = SignalStage.RUN_LAST;
+	}
+
 	private Gee.List<FormalParameter> parameters = new ArrayList<FormalParameter> ();
-	private Method generated_method;
+	/**
+	 * Refers to the default signal handler, which is an anonymous
+	 * function in the scope.
+	 * */
+	public Method default_handler {get; private set;}
 
 	private string cname;
 	
@@ -57,6 +81,8 @@ public class Vala.Signal : Member, Lockable {
 
 	private DataType _return_type;
 
+	private Block _body;
+
 	/**
 	 * Creates a new signal.
 	 *
@@ -179,16 +205,52 @@ public class Vala.Signal : Member, Lockable {
 		foreach (FormalParameter param in parameters) {
 			param.accept (visitor);
 		}
+		if(default_handler != null) {
+			default_handler.accept (visitor);
+		}
 	}
 
 	/**
 	 * Process all associated attributes.
 	 */
+	private void process_signal_attribute(Attribute a) {
+		if(a.has_argument("has_emitter")) {
+			has_emitter = a.get_bool ("has_emitter");
+		}
+		if(a.has_argument("stage")) {
+			var stage_name = a.get_string("stage");
+			switch(stage_name) {
+				case "RUN_FIRST":
+				case "FIRST":
+					stage = SignalStage.RUN_FIRST;
+				break;
+				case "RUN_LAST":
+				case "LAST":
+					stage = SignalStage.RUN_LAST;
+				break;
+				case "RUN_CLEANUP":
+				case "CLEANUP":
+					stage = SignalStage.RUN_CLEANUP;
+				break;
+				default:
+					Report.warning (source_reference,
+					"unknown stage %s".printf(stage_name));
+				break;
+			}
+		}
+	}
+
 	public void process_attributes () {
 		foreach (Attribute a in attributes) {
+			/* Backward compatitable weith HasEmitter,
+			 * should be replace with Signal (has_emitter = true/false)
+			 * */
 			if (a.name == "HasEmitter") {
 				has_emitter = true;
 			}
+			if (a.name == "Signal") {
+				process_signal_attribute(a);
+			}
 		}
 	}
 	
@@ -206,26 +268,6 @@ public class Vala.Signal : Member, Lockable {
 		}
 	}
 
-	public Method get_method_handler () {
-		assert (is_virtual);
-
-		if (generated_method == null) {
-			generated_method = new Method (name, return_type, source_reference);
-			generated_method.access = access;
-			generated_method.is_virtual = true;
-			generated_method.vfunc_name = name;
-			generated_method.signal_reference = this;
-
-			foreach (FormalParameter param in parameters) {
-				generated_method.add_parameter (param);
-			}
-
-			parent_symbol.scope.add (null, generated_method);
-		}
-		
-		return generated_method;
-	}
-
 	public override bool check (SemanticAnalyzer analyzer) {
 		if (checked) {
 			return !error;
@@ -241,7 +283,31 @@ public class Vala.Signal : Member, Lockable {
 			param.check (analyzer);
 		}
 
+		if(!is_virtual && body != null) {
+			Report.error (source_reference, "Only virtual signals can have a default signal handler body");
+		}
+
+
+		if(is_virtual) {
+			default_handler = new Method (name, return_type, source_reference);
+			default_handler.is_virtual = true;
+			default_handler.vfunc_name = name;
+			default_handler.signal_reference = this;
+			default_handler.body = body;
+
+			foreach (FormalParameter param in parameters) {
+				default_handler.add_parameter (param);
+			}
+
+			parent_symbol.scope.add (null, default_handler);
+			default_handler.check (analyzer);
+		}
 		return !error;
 	}
 }
 
+public enum Vala.SignalStage {
+	RUN_FIRST,
+	RUN_LAST,
+	RUN_CLEANUP,
+}
