Last modified: 2014-06-23 16:07:11 UTC

Wikimedia Bugzilla is closed!

Wikimedia migrated from Bugzilla to Phabricator. Bug reports are handled in Wikimedia Phabricator.
This static website is read-only and for historical purposes. It is not possible to log in and except for displaying bug reports and their history, links might be broken. See T52275, the corresponding Phabricator task for complete and up-to-date bug report information.
Bug 50275 - CreateAccount API call doesn't COMMIT the operation
CreateAccount API call doesn't COMMIT the operation
Status: RESOLVED INVALID
Product: MediaWiki
Classification: Unclassified
API (Other open bugs)
1.21.x
All All
: High normal (vote)
: ---
Assigned To: Tyler Romeo
:
Depends on:
Blocks:
  Show dependency treegraph
 
Reported: 2013-06-27 09:48 UTC by Szőts Ákos
Modified: 2014-06-23 16:07 UTC (History)
5 users (show)

See Also:
Web browser: ---
Mobile Platform: ---
Assignee Huggle Beta Tester: ---


Attachments

Description Szőts Ákos 2013-06-27 09:48:25 UTC
The problem in a nutshell is:
- I try to create an account via an API call
- All the queries run successfully and the result is "success"
- At the end of the whole process MediaWiki closes connection without doing a COMMIT thus losing all previous actions

The problem detailed:

1.) I use the following code for creating a new account:
<?php
$nick = 'test45';
$pwd = 'aaaaaa';
$email = 'valid@example.com';

$user = make_fake_request(
        array(
                'action' => 'createaccount',
                'name' => $nick,
                'password' => $pwd,
                'email' => $email,
                'token' => ''
        ));

if (isset($user['createaccount']) && $user['createaccount']['result'] == 'needtoken') {
    $user = make_fake_request( // Felhasználó regisztrálása
            array(
                    'action' => 'createaccount',
                    'name' => $nick,
                    'password' => $pwd,
                    'email' => $email,
                    'token' => $user['createaccount']['token']
            ));

    if (isset($user['createaccount']) && $user['createaccount']['result'] == 'success') {
        echo "OK";
    }
}
?>

The "make_fake_request" function consist of the following:
<?php
require_once ("$IP/includes/WebStart.php");
global $wgRequest;
$request = new DerivativeRequest($wgRequest, $params, true);
$api = new ApiMain($request, true);
$api->execute();
$x = & $api->getResultData();
return $x;
?>

This echoes me "OK" all the time when I fill it with valid data.

2.) In the MySQL query log the following runs:
Connect	
Init DB	
Query	SET /* DatabaseMysql::open */ NAMES utf8
Query	SET /* DatabaseMysql::open */ sql_mode = ''
Query	BEGIN /* DatabaseBase::query (Title::getCascadeProtectionSources) */
Query	SELECT /* Title::getCascadeProtectionSources [...] FROM `templatelinks`,`page_restrictions`,`page` WHERE [...]
Query	SELECT /* Block::newLoad [...] FROM `ipblocks` WHERE [...]
Query	SELECT /* Block::newLoad [...] FROM `ipblocks` WHERE [...]
Query	SELECT /* Title::getCascadeProtectionSources [...] FROM `templatelinks`,`page_restrictions`,`page` WHERE [...]
Query	SELECT /* Title::getCascadeProtectionSources [...] FROM `templatelinks`,`page_restrictions`,`page` WHERE [...]
Query	SELECT /* User::idForName [...] FROM `user` WHERE [...]
Query	SELECT /* User::idFromName [...] FROM `user` WHERE [...]
Query	INSERT /* User::addToDatabase */ IGNORE INTO `user` [...]
Query	SELECT /* User::loadOptions [...] FROM `user_properties` WHERE [...]
Query	DELETE /* User::saveOptions */ FROM `user_properties` WHERE  [...]
Query	UPDATE /* User::saveSettings */  `user` SET  [...]
Query	DELETE /* User::saveOptions */ FROM `user_properties` WHERE  [...]
Query	INSERT /* User::saveOptions */  INTO `user_properties`  [...]
Query	UPDATE /* Title::invalidateCache */  `page` SET  [...]
Query	SELECT /* WikiPage::pageData [...] FROM `page` WHERE [...]
Query	UPDATE /* User::saveSettings */  `user`  [...]
Query	DELETE /* User::saveOptions */ FROM `user_properties` WHERE  [...]
Query	INSERT /* User::saveOptions */  INTO `user_properties`  [...]
Query	UPDATE /* Title::invalidateCache */  `page`  [...]
Query	SELECT /* WikiPage::pageData [...] FROM `page` WHERE [...]
Query	INSERT /* ManualLogEntry::insert */  INTO `logging`  [...]
Query	SELECT /* User::idFromName [...] FROM `user` WHERE [...]
Query	SELECT /* User::loadGroups [...] FROM `user_groups` WHERE [...]
Query	SELECT /* User::getEditCount [...] FROM `user` WHERE [...]
Query	INSERT /* RecentChange::save */  INTO `recentchanges`  [...]
Query	SELECT /* EmailNotification::notifyOnPageChange [...] FROM `watchlist` WHERE [...]
Quit	

3.) As you can see above, there's no COMMIT at the end, so all of the changes will be rolled back as soon as the PHP is closing its connection.

The SQL server is MySQL v5.5.30.
Comment 1 Sam Reed (reedy) 2013-06-27 09:57:33 UTC
In this case it really needs to call $user->addToDatabase() somewhere near to the end

CC'ing named author of the file

Andre: When we have a fix committed etc, this should most definitely be backported to all applicable branches. I'm not sure how widely it's actually used, but a maintenance release could be in order too
Comment 3 Sam Reed (reedy) 2013-06-27 10:26:43 UTC
(In reply to comment #1)
> In this case it really needs to call $user->addToDatabase() somewhere near to
> the end

Looking closer (and more awake), the dangling transaction starts in Title::getCascadeProtectionSources(), which manifests itself as such.

Might not be the API module. In master "getCascadeProtectionSources" doesn't call a begin(), neither does it open a connection to a DB Master
Comment 4 Tyler Romeo 2013-06-27 11:34:57 UTC
To be specific, the transaction starts in "DatabaseBase::query (Title::getCascadeProtectionSources)". The actual method says DatabaseBase::query, which means this is an automatically started transaction (so DBO_TRX is set here).

As for why the implicit transaction is not committing, I'm not too sure, because DatabaseBase::close() automatically commits transactions before it closes the DB connection.
Comment 5 Andre Klapper 2013-06-27 11:40:47 UTC
(In reply to comment #1)
> Andre: When we have a fix committed etc, this should most definitely be
> backported to all applicable branches. I'm not sure how widely it's actually
> used, but a maintenance release could be in order too

==> Setting Backport flag to "requested" (which is "?") and CC'ing hexmode.
Comment 6 Sam Reed (reedy) 2013-06-27 14:57:03 UTC
Out of interest, what version of PHP are you running? On what platform?
Comment 7 Szőts Ákos 2013-06-27 14:58:53 UTC
PHP v5.3.17 on an openSUSE 12.3 x64.
Comment 8 Brad Jorsch 2013-06-27 15:17:13 UTC
This doesn't seem to be an API issue. The issue is that the DBO_TRX transaction is never getting closed. And it looks to me that the problem is that the reporter's weird script is not bothering to call LoadBalancer::shutdown(), which would make this bug RESOLVED INVALID.


(In reply to comment #0)
> The problem in a nutshell is:
> - I try to create an account via an API call

That's not what you're doing here. You're creating an account from a script that is poking at MediaWiki in a non-standard manner.

> - At the end of the whole process MediaWiki closes connection without doing a
> COMMIT thus losing all previous actions

Also wrong. You're never telling MediaWiki to actually close the connection.

Try adding the following to the end of your script and see if it works:
  
  DeferredUpdates::doUpdates();
  $lb = wfGetLBFactory();
  $lb->shutdown();


(In reply to comment #1)
> In this case it really needs to call $user->addToDatabase() somewhere near to
> the end

That's being called in LoginForm::initUser(), which is called from LoginForm::addNewAccountInternal(), which is called from ApiCreateAccount to do the actual user creation.
Comment 9 Szőts Ákos 2013-06-27 15:37:34 UTC
Thank you for the advice. Adding the suggested lines into the code makes it work perfectly.

Well, how standard it is, I don't know. I made this code a year ago (it wasn't so long after all) based entirely upon the official guide [1] with the help of an other page (also recommended inside the guide) [2].

Time flew and it was a mistake not to complete my code with the required changes. Sorry for the false report and thank you for the quick response. I closed it as invalid.

[1]: http://www.mediawiki.org/w/index.php? title=API:Calling_internally&oldid=536426
[2]: http://web.archive.org/web/20120626061757/http://auzigog.com/2009/01/11/creating-a-mediawiki-api-instance-outside-installation-directory/
Comment 10 Brad Jorsch 2013-06-27 15:48:36 UTC
(In reply to comment #9)
> Well, how standard it is, I don't know. I made this code a year ago (it
> wasn't
> so long after all) based entirely upon the official guide [1] with the help
> of
> an other page (also recommended inside the guide) [2].

The first is for calling the API from within MediaWiki, if for some reason that's necessary. But in that case, the standard MediaWiki entry points will have the code to clean things up properly.

The second, unfortunately, appears to have been some random guy spamming a link to his blog.

Ideally either your script should access the API through a web request to api.php or it should be done as a proper maintenance script.[3]


 [3]: https://www.mediawiki.org/wiki/Manual:Writing_maintenance_scripts
Comment 11 Szőts Ákos 2013-06-27 16:01:21 UTC
Oh, I see. Thank you for pointing this out. I think if I have a bit more time, I'll rewrite my script using the standard api.php.

Thank you again for your time.

Note You need to log in before you can comment on or make changes to this bug.


Navigation
Links