[Tutorial] New Timer Bug
#1

NEW TIMER BUG
I am creating this thread to warn server owners that there is a timer bug that creates an infinite timer (or even more timers) that can not be killed. This bug only affects if a timer is repeated; if your timer only works once you do not to worry about it.

I know this is an old bug (I called this thread "New Timer Bug" because few people know about it, as I saw it in some servers...), bugging and lagging their own servers.

It is a programming mistake; you can call it a bug, error, whatever; I call it a bug

It consists in creating a timer with SetTimerEx and calling it twice without killing it. This will create an infinite timer that can be killed just with restarting the server.

This can be dangerous in some cases (specially in big servers), as it produces bugs, lag, player crash, server crash, etc.

If this thread is not clear you can try this code; just type /Timer twice, then try to kill it with /Killer and you will see the result:

Pastebin

How to prevent this? Easy, just kill the timer before creating a new one; for example:

pawn Код:
KillTimer(Connect[playerid]);
Connect[playerid] = SetTimerEx("Test", 1000, true, "i", playerid);
I hope this helps you, good luck
Reply
#2

Never faced this error before. Can you show a source that the bug is alive? I use timer's quite often when writing small scripts, and some repeat; I've never faced this before, ever.
Reply
#3

I wouldn't call this a tutorial, You didn't even explained anything you just pasted a code and it was like "Bwah! Done, thank you for reading my tutorial, REP me please."
Reply
#4

Quote:
Originally Posted by Abagail
Посмотреть сообщение
Never faced this error before. Can you show a source that the bug is alive? I use timer's quite often when writing small scripts, and some repeat; I've never faced this before, ever.
Yeah, it is still alive but sometimes it is not really dangerous; just repeats but it is invisible, causing no real damage or lag.

In those cases it is not very dangerous, but sometimes it can be dangerous, for example if you use it for an action, it will bug that ID, repeating that action infinite times on that ID (one of many examples). Or if you use it in a really big server and that timer is called many times by many players it will lag the server

You can test it yourself:

Pastebin

Quote:
Originally Posted by _Jake_
Посмотреть сообщение
I wouldn't call this a tutorial, You didn't even explained anything you just pasted a code and it was like "Bwah! Done, thank you for reading my tutorial, REP me please."
I do not care about REP, otherwise, I would create other kind of threads

Anyway, I explained the solution but if you want I can explain how that bug works. It assigns the timer another value, making impossible to kill it
Reply
#5

its not a bug
its just a coding mistakes
you can fix that with this
pawn Код:
public OnPlayerCommandText(playerid, cmdtext[])
{
    if(!strcmp(cmdtext, "/Timer", true))
    {
        if(Connect[playerid])
        {
            KillTimer(Connect[playerid]);
            Connect[playerid]=0;
        }
        Connect[playerid] = SetTimerEx("Test", 1000, true, "i", playerid);
        return 1;
    }
    if(!strcmp(cmdtext, "/Killer", true))
    {
        if(Connect[playerid])
        {
            KillTimer(Connect[playerid]);
            Connect[playerid]=0;
        }
        return 1;
    }
    return 0;
}
Reply
#6

Quote:
Originally Posted by Quickie
Посмотреть сообщение
its not a bug
its just a coding mistakes
you can fix that with this
pawn Код:
public OnPlayerCommandText(playerid, cmdtext[])
{
    if(!strcmp(cmdtext, "/Timer", true))
    {
        if(Connect[playerid])
        {
            KillTimer(Connect[playerid]);
            Connect[playerid]=0;
        }
        Connect[playerid] = SetTimerEx("Test", 1000, true, "i", playerid);
        return 1;
    }
    if(!strcmp(cmdtext, "/Killer", true))
    {
        if(Connect[playerid])
        {
            KillTimer(Connect[playerid]);
            Connect[playerid]=0;
        }
        return 1;
    }
    return 0;
}
That is true:

Quote:

It is a programming mistake; you can call it a bug, error, whatever; I call it a bug
It can be fixed in both ways, I prefer the simplest one

pawn Код:
KillTimer(Connect[playerid]);
Connect[playerid] = SetTimerEx("Test", 1000, true, "i", playerid);
But that code is good. Also, thanks for feedback, +REP
Reply
#7

This is not a bug..

It happens on any programming language. If you create a timer and then create another one and store the ID in the same variable, then it will be inaccessible, which is therefore called a memory leak because the first timer has no reference.

A fix is pretty simple: just use "-1" as an indication that the timer is not running.

pawn Код:
#define INVALID_TIMER_ID (-1)

new
    g_iTimerID[MAX_PLAYERS]
;

public OnPlayerConnect(playerid) {
    g_iTimerID[playerid] = INVALID_TIMER_ID;
}

public OnPlayerDisconnect(playerid, reason) {

    if (g_iTimerID[playerid] != INVALID_TIMER_ID) {
        KillTimer(g_iTimerID[playerid]);
    }
}

CMD:timer(playerid, params[]) {
   
    if (g_iTimerID[playerid] != INVALID_TIMER_ID)
        KillTimer(g_iTimerID[playerid]);
   
    else
        g_iTimerID[playerid] = SetTimerEx("...", 1500, false, "d", playerid);
}
Reply
#8

Quote:
Originally Posted by Emmet_
Посмотреть сообщение
This is not a bug..

It happens on any programming language. If you create a timer and then create another one and store the ID in the same variable, then it will be inaccessible, which is therefore called a memory leak because the first timer has no reference.

A fix is pretty simple: just use "-1" as an indication that the timer is not running.

pawn Код:
#define INVALID_TIMER_ID (-1)

new
    g_iTimerID[MAX_PLAYERS]
;

public OnPlayerConnect(playerid) {
    g_iTimerID[playerid] = INVALID_TIMER_ID;
}

public OnPlayerDisconnect(playerid, reason) {

    if (g_iTimerID[playerid] != INVALID_TIMER_ID) {
        KillTimer(g_iTimerID[playerid]);
    }
}

CMD:timer(playerid, params[]) {
   
    if (g_iTimerID[playerid] != INVALID_TIMER_ID)
        KillTimer(g_iTimerID[playerid]);
   
    else
        g_iTimerID[playerid] = SetTimerEx("...", 1500, false, "d", playerid);
}
What I said:

Quote:

It is a programming mistake; you can call it a bug, error, whatever; I call it a bug
Simplest explanation for newbies and new programmers. I created this topic because I saw many servers and programmers with this problem.

Thanks for feedback, +REP
Reply


Forum Jump:


Users browsing this thread: 5 Guest(s)