Commit a6fc012c authored by Linus Torvalds's avatar Linus Torvalds

Merge common signal handling fault handling in generic code.

parent 2355757b
...@@ -469,9 +469,7 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, ...@@ -469,9 +469,7 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
return; return;
give_sigsegv: give_sigsegv:
if (sig == SIGSEGV) force_sigsegv(sig, current);
ka->sa.sa_handler = SIG_DFL;
force_sig(SIGSEGV, current);
} }
static void static void
...@@ -533,9 +531,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -533,9 +531,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
return; return;
give_sigsegv: give_sigsegv:
if (sig == SIGSEGV) force_sigsegv(sig, current);
ka->sa.sa_handler = SIG_DFL;
force_sig(SIGSEGV, current);
} }
......
...@@ -639,9 +639,7 @@ handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset, ...@@ -639,9 +639,7 @@ handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset,
return; return;
} }
if (sig == SIGSEGV) force_sigsegv(sig, tsk);
ka->sa.sa_handler = SIG_DFL;
force_sig(SIGSEGV, tsk);
} }
/* /*
......
...@@ -465,9 +465,7 @@ handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset, ...@@ -465,9 +465,7 @@ handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset,
return; return;
} }
if (sig == SIGSEGV) force_sigsegv(sig, tsk);
ka->sa.sa_handler = SIG_DFL;
force_sig(SIGSEGV, tsk);
} }
/* /*
......
...@@ -409,9 +409,7 @@ static void setup_frame(int sig, struct k_sigaction *ka, ...@@ -409,9 +409,7 @@ static void setup_frame(int sig, struct k_sigaction *ka,
return; return;
give_sigsegv: give_sigsegv:
if (sig == SIGSEGV) force_sigsegv(sig, current);
ka->sa.sa_handler = SIG_DFL;
force_sig(SIGSEGV, current);
} }
static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
...@@ -475,9 +473,7 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -475,9 +473,7 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
return; return;
give_sigsegv: give_sigsegv:
if (sig == SIGSEGV) force_sigsegv(sig, current);
ka->sa.sa_handler = SIG_DFL;
force_sig(SIGSEGV, current);
} }
/* /*
......
...@@ -391,9 +391,7 @@ static void setup_frame (int sig, struct k_sigaction *ka, ...@@ -391,9 +391,7 @@ static void setup_frame (int sig, struct k_sigaction *ka,
return; return;
give_sigsegv: give_sigsegv:
if (sig == SIGSEGV) force_sigsegv(sig, current);
ka->sa.sa_handler = SIG_DFL;
force_sig(SIGSEGV, current);
} }
static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info, static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
...@@ -443,9 +441,7 @@ static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -443,9 +441,7 @@ static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
return; return;
give_sigsegv: give_sigsegv:
if (sig == SIGSEGV) force_sigsegv(sig, current);
ka->sa.sa_handler = SIG_DFL;
force_sig(SIGSEGV, current);
} }
static inline void static inline void
......
...@@ -411,9 +411,7 @@ static void setup_frame(int sig, struct k_sigaction *ka, ...@@ -411,9 +411,7 @@ static void setup_frame(int sig, struct k_sigaction *ka,
return; return;
give_sigsegv: give_sigsegv:
if (sig == SIGSEGV) force_sigsegv(sig, current);
ka->sa.sa_handler = SIG_DFL;
force_sig(SIGSEGV, current);
} }
static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
...@@ -492,9 +490,7 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -492,9 +490,7 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
return; return;
give_sigsegv: give_sigsegv:
if (sig == SIGSEGV) force_sigsegv(sig, current);
ka->sa.sa_handler = SIG_DFL;
force_sig(SIGSEGV, current);
} }
/* /*
......
...@@ -882,9 +882,7 @@ setup_frame_ia32 (int sig, struct k_sigaction *ka, sigset_t *set, struct pt_regs ...@@ -882,9 +882,7 @@ setup_frame_ia32 (int sig, struct k_sigaction *ka, sigset_t *set, struct pt_regs
return 1; return 1;
give_sigsegv: give_sigsegv:
if (sig == SIGSEGV) force_sigsegv(sig, current);
ka->sa.sa_handler = SIG_DFL;
force_sig(SIGSEGV, current);
return 0; return 0;
} }
...@@ -952,9 +950,7 @@ setup_rt_frame_ia32 (int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -952,9 +950,7 @@ setup_rt_frame_ia32 (int sig, struct k_sigaction *ka, siginfo_t *info,
return 1; return 1;
give_sigsegv: give_sigsegv:
if (sig == SIGSEGV) force_sigsegv(sig, current);
ka->sa.sa_handler = SIG_DFL;
force_sig(SIGSEGV, current);
return 0; return 0;
} }
......
...@@ -842,9 +842,7 @@ static void setup_frame (int sig, struct k_sigaction *ka, ...@@ -842,9 +842,7 @@ static void setup_frame (int sig, struct k_sigaction *ka,
return; return;
give_sigsegv: give_sigsegv:
if (sig == SIGSEGV) force_sigsegv(sig, current);
ka->sa.sa_handler = SIG_DFL;
force_sig(SIGSEGV, current);
goto adjust_stack; goto adjust_stack;
} }
...@@ -925,9 +923,7 @@ static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -925,9 +923,7 @@ static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
return; return;
give_sigsegv: give_sigsegv:
if (sig == SIGSEGV) force_sigsegv(sig, current);
ka->sa.sa_handler = SIG_DFL;
force_sig(SIGSEGV, current);
goto adjust_stack; goto adjust_stack;
} }
......
...@@ -616,9 +616,7 @@ static void setup_frame (int sig, struct k_sigaction *ka, ...@@ -616,9 +616,7 @@ static void setup_frame (int sig, struct k_sigaction *ka,
return; return;
give_sigsegv: give_sigsegv:
if (sig == SIGSEGV) force_sigsegv(sig, current);
ka->sa.sa_handler = SIG_DFL;
force_sig(SIGSEGV, current);
goto adjust_stack; goto adjust_stack;
} }
...@@ -685,9 +683,7 @@ static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -685,9 +683,7 @@ static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
return; return;
give_sigsegv: give_sigsegv:
if (sig == SIGSEGV) force_sigsegv(sig, current);
ka->sa.sa_handler = SIG_DFL;
force_sig(SIGSEGV, current);
goto adjust_stack; goto adjust_stack;
} }
......
...@@ -121,9 +121,7 @@ static void setup_irix_frame(struct k_sigaction *ka, struct pt_regs *regs, ...@@ -121,9 +121,7 @@ static void setup_irix_frame(struct k_sigaction *ka, struct pt_regs *regs,
return; return;
segv_and_exit: segv_and_exit:
if (signr == SIGSEGV) force_sigsegv(signr, current);
ka->sa.sa_handler = SIG_DFL;
force_sig(SIGSEGV, current);
} }
static void inline static void inline
......
...@@ -406,9 +406,7 @@ static void inline setup_frame(struct k_sigaction * ka, struct pt_regs *regs, ...@@ -406,9 +406,7 @@ static void inline setup_frame(struct k_sigaction * ka, struct pt_regs *regs,
return; return;
give_sigsegv: give_sigsegv:
if (signr == SIGSEGV) force_sigsegv(signr, current);
ka->sa.sa_handler = SIG_DFL;
force_sig(SIGSEGV, current);
} }
#endif #endif
...@@ -475,9 +473,7 @@ static void inline setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs, ...@@ -475,9 +473,7 @@ static void inline setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs,
return; return;
give_sigsegv: give_sigsegv:
if (signr == SIGSEGV) force_sigsegv(signr, current);
ka->sa.sa_handler = SIG_DFL;
force_sig(SIGSEGV, current);
} }
extern void setup_rt_frame_n32(struct k_sigaction * ka, extern void setup_rt_frame_n32(struct k_sigaction * ka,
......
...@@ -574,9 +574,7 @@ static inline void setup_frame(struct k_sigaction * ka, struct pt_regs *regs, ...@@ -574,9 +574,7 @@ static inline void setup_frame(struct k_sigaction * ka, struct pt_regs *regs,
return; return;
give_sigsegv: give_sigsegv:
if (signr == SIGSEGV) force_sigsegv(signr, current);
ka->sa.sa_handler = SIG_DFL;
force_sig(SIGSEGV, current);
} }
static inline void setup_rt_frame(struct k_sigaction * ka, static inline void setup_rt_frame(struct k_sigaction * ka,
...@@ -647,9 +645,7 @@ static inline void setup_rt_frame(struct k_sigaction * ka, ...@@ -647,9 +645,7 @@ static inline void setup_rt_frame(struct k_sigaction * ka,
return; return;
give_sigsegv: give_sigsegv:
if (signr == SIGSEGV) force_sigsegv(signr, current);
ka->sa.sa_handler = SIG_DFL;
force_sig(SIGSEGV, current);
} }
static inline void handle_signal(unsigned long sig, siginfo_t *info, static inline void handle_signal(unsigned long sig, siginfo_t *info,
......
...@@ -208,7 +208,5 @@ void setup_rt_frame_n32(struct k_sigaction * ka, ...@@ -208,7 +208,5 @@ void setup_rt_frame_n32(struct k_sigaction * ka,
return; return;
give_sigsegv: give_sigsegv:
if (signr == SIGSEGV) force_sigsegv(signr, current);
ka->sa.sa_handler = SIG_DFL;
force_sig(SIGSEGV, current);
} }
...@@ -404,9 +404,7 @@ handle_rt_signal(unsigned long sig, struct k_sigaction *ka, ...@@ -404,9 +404,7 @@ handle_rt_signal(unsigned long sig, struct k_sigaction *ka,
printk("badframe in handle_rt_signal, regs=%p frame=%p newsp=%lx\n", printk("badframe in handle_rt_signal, regs=%p frame=%p newsp=%lx\n",
regs, frame, newsp); regs, frame, newsp);
#endif #endif
if (sig == SIGSEGV) force_sigsegv(sig, current);
ka->sa.sa_handler = SIG_DFL;
force_sig(SIGSEGV, current);
} }
static int do_setcontext(struct ucontext __user *ucp, struct pt_regs *regs, int sig) static int do_setcontext(struct ucontext __user *ucp, struct pt_regs *regs, int sig)
...@@ -556,9 +554,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, ...@@ -556,9 +554,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
printk("badframe in handle_signal, regs=%p frame=%p newsp=%lx\n", printk("badframe in handle_signal, regs=%p frame=%p newsp=%lx\n",
regs, frame, newsp); regs, frame, newsp);
#endif #endif
if (sig == SIGSEGV) force_sigsegv(sig, current);
ka->sa.sa_handler = SIG_DFL;
force_sig(SIGSEGV, current);
} }
/* /*
......
...@@ -699,9 +699,7 @@ static void handle_rt_signal32(unsigned long sig, struct k_sigaction *ka, ...@@ -699,9 +699,7 @@ static void handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,
printk("badframe in handle_rt_signal, regs=%p frame=%p newsp=%lx\n", printk("badframe in handle_rt_signal, regs=%p frame=%p newsp=%lx\n",
regs, frame, newsp); regs, frame, newsp);
#endif #endif
if (sig == SIGSEGV) force_sigsegv(sig, current);
ka->sa.sa_handler = SIG_DFL;
force_sig(SIGSEGV, current);
} }
static long do_setcontext32(struct ucontext32 __user *ucp, struct pt_regs *regs, int sig) static long do_setcontext32(struct ucontext32 __user *ucp, struct pt_regs *regs, int sig)
...@@ -864,9 +862,7 @@ static void handle_signal32(unsigned long sig, struct k_sigaction *ka, ...@@ -864,9 +862,7 @@ static void handle_signal32(unsigned long sig, struct k_sigaction *ka,
printk("badframe in handle_signal, regs=%p frame=%x newsp=%x\n", printk("badframe in handle_signal, regs=%p frame=%x newsp=%x\n",
regs, frame, *newspp); regs, frame, *newspp);
#endif #endif
if (sig == SIGSEGV) force_sigsegv(sig, current);
ka->sa.sa_handler = SIG_DFL;
force_sig(SIGSEGV, current);
} }
/* /*
......
...@@ -552,9 +552,7 @@ static void setup_frame32(int sig, struct k_sigaction *ka, ...@@ -552,9 +552,7 @@ static void setup_frame32(int sig, struct k_sigaction *ka,
return; return;
give_sigsegv: give_sigsegv:
if (sig == SIGSEGV) force_sigsegv(sig, current);
ka->sa.sa_handler = SIG_DFL;
force_sig(SIGSEGV, current);
} }
static void setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info, static void setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info,
...@@ -604,9 +602,7 @@ static void setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -604,9 +602,7 @@ static void setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info,
return; return;
give_sigsegv: give_sigsegv:
if (sig == SIGSEGV) force_sigsegv(sig, current);
ka->sa.sa_handler = SIG_DFL;
force_sig(SIGSEGV, current);
} }
/* /*
......
...@@ -358,9 +358,7 @@ static void setup_frame(int sig, struct k_sigaction *ka, ...@@ -358,9 +358,7 @@ static void setup_frame(int sig, struct k_sigaction *ka,
return; return;
give_sigsegv: give_sigsegv:
if (sig == SIGSEGV) force_sigsegv(sig, current);
ka->sa.sa_handler = SIG_DFL;
force_sig(SIGSEGV, current);
} }
static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
...@@ -414,9 +412,7 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -414,9 +412,7 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
return; return;
give_sigsegv: give_sigsegv:
if (sig == SIGSEGV) force_sigsegv(sig, current);
ka->sa.sa_handler = SIG_DFL;
force_sig(SIGSEGV, current);
} }
/* /*
......
...@@ -413,9 +413,7 @@ static void setup_frame(int sig, struct k_sigaction *ka, ...@@ -413,9 +413,7 @@ static void setup_frame(int sig, struct k_sigaction *ka,
return; return;
give_sigsegv: give_sigsegv:
if (sig == SIGSEGV) force_sigsegv(sig, current);
ka->sa.sa_handler = SIG_DFL;
force_sig(SIGSEGV, current);
} }
static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
...@@ -490,9 +488,7 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -490,9 +488,7 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
return; return;
give_sigsegv: give_sigsegv:
if (sig == SIGSEGV) force_sigsegv(sig, current);
ka->sa.sa_handler = SIG_DFL;
force_sig(SIGSEGV, current);
} }
/* /*
......
...@@ -520,9 +520,7 @@ static void setup_frame(int sig, struct k_sigaction *ka, ...@@ -520,9 +520,7 @@ static void setup_frame(int sig, struct k_sigaction *ka,
return; return;
give_sigsegv: give_sigsegv:
if (sig == SIGSEGV) force_sigsegv(sig, current);
ka->sa.sa_handler = SIG_DFL;
force_sig(SIGSEGV, current);
} }
static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
...@@ -628,9 +626,7 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -628,9 +626,7 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
return; return;
give_sigsegv: give_sigsegv:
if (sig == SIGSEGV) force_sigsegv(sig, current);
ka->sa.sa_handler = SIG_DFL;
force_sig(SIGSEGV, current);
} }
/* /*
......
...@@ -31,17 +31,6 @@ ...@@ -31,17 +31,6 @@
EXPORT_SYMBOL(block_signals); EXPORT_SYMBOL(block_signals);
EXPORT_SYMBOL(unblock_signals); EXPORT_SYMBOL(unblock_signals);
static void force_segv(int sig)
{
if(sig == SIGSEGV){
struct k_sigaction *ka;
ka = &current->sighand->action[SIGSEGV - 1];
ka->sa.sa_handler = SIG_DFL;
}
force_sig(SIGSEGV, current);
}
#define _S(nr) (1<<((nr)-1)) #define _S(nr) (1<<((nr)-1))
#define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP))) #define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
...@@ -124,7 +113,7 @@ static int handle_signal(struct pt_regs *regs, unsigned long signr, ...@@ -124,7 +113,7 @@ static int handle_signal(struct pt_regs *regs, unsigned long signr,
return(0); return(0);
segv: segv:
force_segv(signr); force_sigsegv(signr, current);
return(1); return(1);
} }
......
...@@ -344,9 +344,7 @@ static void setup_frame(int sig, struct k_sigaction *ka, ...@@ -344,9 +344,7 @@ static void setup_frame(int sig, struct k_sigaction *ka,
return; return;
give_sigsegv: give_sigsegv:
if (sig == SIGSEGV) force_sigsegv(sig, current);
ka->sa.sa_handler = SIG_DFL;
force_sig(SIGSEGV, current);
} }
static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
...@@ -421,9 +419,7 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -421,9 +419,7 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
return; return;
give_sigsegv: give_sigsegv:
if (sig == SIGSEGV) force_sigsegv(sig, current);
ka->sa.sa_handler = SIG_DFL;
force_sig(SIGSEGV, current);
} }
/* /*
......
...@@ -499,9 +499,7 @@ void ia32_setup_frame(int sig, struct k_sigaction *ka, ...@@ -499,9 +499,7 @@ void ia32_setup_frame(int sig, struct k_sigaction *ka,
return; return;
give_sigsegv: give_sigsegv:
if (sig == SIGSEGV) force_sigsegv(sig, current);
ka->sa.sa_handler = SIG_DFL;
signal_fault(regs,frame,"32bit signal deliver");
} }
void ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, void ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
...@@ -595,8 +593,6 @@ void ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -595,8 +593,6 @@ void ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
return; return;
give_sigsegv: give_sigsegv:
if (sig == SIGSEGV) force_sigsegv(sig, current);
ka->sa.sa_handler = SIG_DFL;
signal_fault(regs, frame, "32bit rt signal setup");
} }
...@@ -329,9 +329,7 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -329,9 +329,7 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
return; return;
give_sigsegv: give_sigsegv:
if (sig == SIGSEGV) force_sigsegv(sig, current);
ka->sa.sa_handler = SIG_DFL;
signal_fault(regs,frame,"signal deliver");
} }
/* /*
......
...@@ -718,6 +718,7 @@ extern void unblock_all_signals(void); ...@@ -718,6 +718,7 @@ extern void unblock_all_signals(void);
extern void release_task(struct task_struct * p); extern void release_task(struct task_struct * p);
extern int send_sig_info(int, struct siginfo *, struct task_struct *); extern int send_sig_info(int, struct siginfo *, struct task_struct *);
extern int send_group_sig_info(int, struct siginfo *, struct task_struct *); extern int send_group_sig_info(int, struct siginfo *, struct task_struct *);
extern int force_sigsegv(int, struct task_struct *);
extern int force_sig_info(int, struct siginfo *, struct task_struct *); extern int force_sig_info(int, struct siginfo *, struct task_struct *);
extern int __kill_pg_info(int sig, struct siginfo *info, pid_t pgrp); extern int __kill_pg_info(int sig, struct siginfo *info, pid_t pgrp);
extern int kill_pg_info(int, struct siginfo *, pid_t); extern int kill_pg_info(int, struct siginfo *, pid_t);
......
...@@ -1243,6 +1243,25 @@ force_sig(int sig, struct task_struct *p) ...@@ -1243,6 +1243,25 @@ force_sig(int sig, struct task_struct *p)
force_sig_info(sig, (void*)1L, p); force_sig_info(sig, (void*)1L, p);
} }
/*
* When things go south during signal handling, we
* will force a SIGSEGV. And if the signal that caused
* the problem was already a SIGSEGV, we'll want to
* make sure we don't even try to deliver the signal..
*/
int
force_sigsegv(int sig, struct task_struct *p)
{
if (sig == SIGSEGV) {
unsigned long flags;
spin_lock_irqsave(&p->sighand->siglock, flags);
p->sighand->action[sig - 1].sa.sa_handler = SIG_DFL;
spin_unlock_irqrestore(&p->sighand->siglock, flags);
}
force_sig(SIGSEGV, p);
return 0;
}
int int
kill_pg(pid_t pgrp, int sig, int priv) kill_pg(pid_t pgrp, int sig, int priv)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment